Move drm related device initialization into loongson_drm_master_bind(), As we need to wait all other submodules ready before we could register the drm device to userspace. Move output related things into subdriver, fullfill the implement under the new framework. Signed-off-by: Sui Jingfeng <sui.jingfeng@xxxxxxxxx> --- drivers/gpu/drm/loongson/lsdc_drv.c | 187 +++++++++--------- drivers/gpu/drm/loongson/lsdc_drv.h | 22 +-- drivers/gpu/drm/loongson/lsdc_output.c | 41 ++++ drivers/gpu/drm/loongson/lsdc_output.h | 16 +- drivers/gpu/drm/loongson/lsdc_output_7a1000.c | 3 +- drivers/gpu/drm/loongson/lsdc_output_7a2000.c | 15 +- 6 files changed, 152 insertions(+), 132 deletions(-) diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c b/drivers/gpu/drm/loongson/lsdc_drv.c index 45c30e3d178f..796da5c3c2ee 100644 --- a/drivers/gpu/drm/loongson/lsdc_drv.c +++ b/drivers/gpu/drm/loongson/lsdc_drv.c @@ -69,31 +69,6 @@ static int lsdc_modeset_init(struct lsdc_device *ldev, unsigned int i; int ret; - for (i = 0; i < num_crtc; i++) { - dispipe = &ldev->dispipe[i]; - - /* We need an index before crtc is initialized */ - dispipe->index = i; - - ret = funcs->create_i2c(ddev, dispipe, i); - if (ret) - return ret; - } - - for (i = 0; i < num_crtc; i++) { - struct i2c_adapter *ddc = NULL; - - dispipe = &ldev->dispipe[i]; - if (dispipe->li2c) - ddc = &dispipe->li2c->adapter; - - ret = funcs->output_init(ddev, dispipe, ddc, i); - if (ret) - return ret; - - ldev->num_output++; - } - for (i = 0; i < num_crtc; i++) { dispipe = &ldev->dispipe[i]; @@ -189,30 +164,17 @@ static int lsdc_get_dedicated_vram(struct lsdc_device *ldev, return (size > SZ_1M) ? 0 : -ENODEV; } -static struct lsdc_device * -lsdc_create_device(struct pci_dev *pdev, - const struct lsdc_desc *descp, - const struct drm_driver *driver) +static int lsdc_device_init(struct lsdc_device *ldev, + const struct lsdc_desc *descp, + const struct drm_driver *driver) { - struct lsdc_device *ldev; - struct drm_device *ddev; + struct drm_device *ddev = &ldev->base; int ret; - ldev = devm_drm_dev_alloc(&pdev->dev, driver, struct lsdc_device, base); - if (IS_ERR(ldev)) - return ldev; - - ldev->dc = pdev; - ldev->descp = descp; - - ddev = &ldev->base; - - loongson_gfxpll_create(ddev, &ldev->gfxpll); - - ret = lsdc_get_dedicated_vram(ldev, pdev, descp); + ret = lsdc_get_dedicated_vram(ldev, ldev->dc, ldev->descp); if (ret) { drm_err(ddev, "Init VRAM failed: %d\n", ret); - return ERR_PTR(ret); + return ret; } ret = drm_aperture_remove_conflicting_framebuffers(ldev->vram_base, @@ -220,36 +182,25 @@ lsdc_create_device(struct pci_dev *pdev, driver); if (ret) { drm_err(ddev, "Remove firmware framebuffers failed: %d\n", ret); - return ERR_PTR(ret); + return ret; } ret = lsdc_ttm_init(ldev); if (ret) { drm_err(ddev, "Memory manager init failed: %d\n", ret); - return ERR_PTR(ret); + return ret; } lsdc_gem_init(ddev); /* Bar 0 of the DC device contains the MMIO register's base address */ - ldev->reg_base = pcim_iomap(pdev, 0, 0); + ldev->reg_base = pcim_iomap(ldev->dc, 0, 0); if (!ldev->reg_base) - return ERR_PTR(-ENODEV); + return -ENODEV; spin_lock_init(&ldev->reglock); - ret = lsdc_mode_config_init(ddev, descp); - if (ret) - return ERR_PTR(ret); - - ret = lsdc_modeset_init(ldev, descp->num_of_crtc, descp->funcs, - loongson_vblank); - if (ret) - return ERR_PTR(ret); - - drm_mode_config_reset(ddev); - - return ldev; + return 0; } /* For multiple GPU driver instance co-exixt in the system */ @@ -261,20 +212,64 @@ static unsigned int lsdc_vga_set_decode(struct pci_dev *pdev, bool state) static int loongson_drm_master_bind(struct device *dev) { + struct lsdc_device *ldev = dev_get_drvdata(dev); + const struct lsdc_desc *descp = ldev->descp; + struct drm_device *ddev = &ldev->base; int ret; - ret = component_bind_all(dev, NULL); + if (loongson_vblank) { + struct pci_dev *pdev = to_pci_dev(dev); + + ret = drm_vblank_init(ddev, descp->num_of_crtc); + if (ret) + return ret; + + ret = devm_request_irq(dev, pdev->irq, + descp->funcs->irq_handler, + IRQF_SHARED, + dev_name(dev), ddev); + if (ret) { + drm_err(ddev, "Failed to register interrupt: %d\n", ret); + return ret; + } + + drm_info(ddev, "registered irq: %u\n", pdev->irq); + } + + ret = lsdc_mode_config_init(ddev, descp); + if (ret) + return ret; + + ret = component_bind_all(dev, ddev); if (ret) { dev_err(dev, "master bind all failed: %d\n", ret); return ret; } + ret = lsdc_modeset_init(ldev, descp->num_of_crtc, descp->funcs, + loongson_vblank); + if (ret) + return ret; + + drm_mode_config_reset(ddev); + + drm_kms_helper_poll_init(ddev); + + ret = drm_dev_register(ddev, 0); + if (ret) + return ret; + + drm_fbdev_ttm_setup(ddev, 32); + return 0; } static void loongson_drm_master_unbind(struct device *dev) { - component_unbind_all(dev, NULL); + struct lsdc_device *ldev = dev_get_drvdata(dev); + struct drm_device *ddev = &ldev->base; + + component_unbind_all(dev, ddev); return; } @@ -288,7 +283,6 @@ static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct component_match *matches = NULL; const struct lsdc_desc *descp; - struct drm_device *ddev; struct lsdc_device *ldev; int ret; int i; @@ -310,10 +304,31 @@ static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "Found %s, revision: %u", to_loongson_gfx(descp)->model, pdev->revision); - ldev = lsdc_create_device(pdev, descp, &lsdc_drm_driver); + ldev = devm_drm_dev_alloc(&pdev->dev, &lsdc_drm_driver, + struct lsdc_device, base); if (IS_ERR(ldev)) return PTR_ERR(ldev); + pci_set_drvdata(pdev, ldev); + + ldev->dc = pdev; + ldev->descp = descp; + + loongson_gfxpll_create(&ldev->base, &ldev->gfxpll); + + ret = lsdc_device_init(ldev, descp, &lsdc_drm_driver); + if (ret) + return ret; + + for (i = 0; i < descp->num_of_crtc; ++i) { + struct lsdc_display_pipe *dispipe = &ldev->dispipe[i]; + const struct lsdc_kms_funcs *funcs = descp->funcs; + + ret = funcs->create_i2c(&ldev->base, dispipe, i); + if (ret) + return ret; + } + for (i = 0; i < descp->num_of_crtc; ++i) { ret = lsdc_output_preinit(&pdev->dev, descp, i, &ldev->childs[i]); @@ -333,44 +348,15 @@ static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "loongson add component: %u\n", ret); - ddev = &ldev->base; - - pci_set_drvdata(pdev, ddev); - vga_client_register(pdev, lsdc_vga_set_decode); - drm_kms_helper_poll_init(ddev); - - if (loongson_vblank) { - ret = drm_vblank_init(ddev, descp->num_of_crtc); - if (ret) - return ret; - - ret = devm_request_irq(&pdev->dev, pdev->irq, - descp->funcs->irq_handler, - IRQF_SHARED, - dev_name(&pdev->dev), ddev); - if (ret) { - drm_err(ddev, "Failed to register interrupt: %d\n", ret); - return ret; - } - - drm_info(ddev, "registered irq: %u\n", pdev->irq); - } - - ret = drm_dev_register(ddev, 0); - if (ret) - return ret; - - drm_fbdev_ttm_setup(ddev, 32); - return 0; } static void lsdc_pci_remove(struct pci_dev *pdev) { - struct drm_device *ddev = pci_get_drvdata(pdev); - struct lsdc_device *ldev = to_lsdc(ddev); + struct lsdc_device *ldev = pci_get_drvdata(pdev); + struct drm_device *ddev = &ldev->base; unsigned int i; drm_dev_unregister(ddev); @@ -388,7 +374,10 @@ static void lsdc_pci_remove(struct pci_dev *pdev) static void lsdc_pci_shutdown(struct pci_dev *pdev) { - drm_atomic_helper_shutdown(pci_get_drvdata(pdev)); + struct lsdc_device *ldev = pci_get_drvdata(pdev); + struct drm_device *ddev = &ldev->base; + + drm_atomic_helper_shutdown(ddev); } static int lsdc_drm_freeze(struct drm_device *ddev) @@ -442,7 +431,8 @@ static int lsdc_drm_freeze(struct drm_device *ddev) static int lsdc_drm_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *ddev = pci_get_drvdata(pdev); + struct lsdc_device *ldev = pci_get_drvdata(pdev); + struct drm_device *ddev = &ldev->base; return drm_mode_config_helper_resume(ddev); } @@ -450,7 +440,8 @@ static int lsdc_drm_resume(struct device *dev) static int lsdc_pm_freeze(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *ddev = pci_get_drvdata(pdev); + struct lsdc_device *ldev = pci_get_drvdata(pdev); + struct drm_device *ddev = &ldev->base; return lsdc_drm_freeze(ddev); } diff --git a/drivers/gpu/drm/loongson/lsdc_drv.h b/drivers/gpu/drm/loongson/lsdc_drv.h index 86061207851d..2a291a4a0827 100644 --- a/drivers/gpu/drm/loongson/lsdc_drv.h +++ b/drivers/gpu/drm/loongson/lsdc_drv.h @@ -173,33 +173,15 @@ struct lsdc_cursor { struct lsdc_device *ldev; }; -static inline struct lsdc_output * -connector_to_lsdc_output(struct drm_connector *connector) -{ - return container_of(connector, struct lsdc_output, connector); -} - -static inline struct lsdc_output * -encoder_to_lsdc_output(struct drm_encoder *encoder) -{ - return container_of(encoder, struct lsdc_output, encoder); -} - struct lsdc_display_pipe { struct lsdc_crtc crtc; struct lsdc_primary primary; struct lsdc_cursor cursor; - struct lsdc_output output; + struct lsdc_output *output; struct lsdc_i2c *li2c; unsigned int index; }; -static inline struct lsdc_display_pipe * -output_to_display_pipe(struct lsdc_output *output) -{ - return container_of(output, struct lsdc_display_pipe, output); -} - struct lsdc_kms_funcs { irqreturn_t (*irq_handler)(int irq, void *arg); @@ -208,7 +190,7 @@ struct lsdc_kms_funcs { unsigned int index); int (*output_init)(struct drm_device *ddev, - struct lsdc_display_pipe *dispipe, + struct lsdc_output *output, struct i2c_adapter *ddc, unsigned int index); diff --git a/drivers/gpu/drm/loongson/lsdc_output.c b/drivers/gpu/drm/loongson/lsdc_output.c index b1a9c6123615..28639a1e4407 100644 --- a/drivers/gpu/drm/loongson/lsdc_output.c +++ b/drivers/gpu/drm/loongson/lsdc_output.c @@ -62,6 +62,30 @@ int lsdc_output_preinit(struct device *parent, return 0; } +static int lsdc_output_postinit(struct lsdc_output *output, + struct drm_device *ddev, + struct lsdc_display_pipe *dispipe, + unsigned int pipe) +{ + struct lsdc_device *ldev = to_lsdc(ddev); + const struct lsdc_kms_funcs *kms_funcs = ldev->descp->funcs; + struct i2c_adapter *ddc = NULL; + int ret; + + if (dispipe->li2c) + ddc = &dispipe->li2c->adapter; + + pipe = output->descp->pipe; + + ret = kms_funcs->output_init(&ldev->base, output, ddc, pipe); + if (ret) + return ret; + + dispipe->output = output; + + return 0; +} + /* * dev stand for the port@0, port@1, ..., port@n of the dispplay controller */ @@ -69,6 +93,23 @@ static int lsdc_output_port_bind(struct device *dev, struct device *master, void *data) { + struct lsdc_output *output = dev_get_drvdata(dev); + struct drm_device *ddev = data; + struct lsdc_device *ldev = to_lsdc(ddev); + unsigned int pipe; + int ret; + + pipe = output->descp->pipe; + + ret = lsdc_output_postinit(output, ddev, &ldev->dispipe[pipe], pipe); + if (ret) + return ret; + + ldev->num_output++; + + drm_info(ddev, "Output port-%d bound, type: %s\n", + pipe, output->descp->type); + return 0; } diff --git a/drivers/gpu/drm/loongson/lsdc_output.h b/drivers/gpu/drm/loongson/lsdc_output.h index 195b74da194d..684a5b19bc70 100644 --- a/drivers/gpu/drm/loongson/lsdc_output.h +++ b/drivers/gpu/drm/loongson/lsdc_output.h @@ -23,13 +23,25 @@ struct lsdc_output { struct lsdc_output_desc *descp; }; +static inline struct lsdc_output * +connector_to_lsdc_output(struct drm_connector *connector) +{ + return container_of(connector, struct lsdc_output, connector); +} + +static inline struct lsdc_output * +encoder_to_lsdc_output(struct drm_encoder *encoder) +{ + return container_of(encoder, struct lsdc_output, encoder); +} + int ls7a1000_output_init(struct drm_device *ddev, - struct lsdc_display_pipe *dispipe, + struct lsdc_output *output, struct i2c_adapter *ddc, unsigned int index); int ls7a2000_output_init(struct drm_device *ldev, - struct lsdc_display_pipe *dispipe, + struct lsdc_output *output, struct i2c_adapter *ddc, unsigned int index); diff --git a/drivers/gpu/drm/loongson/lsdc_output_7a1000.c b/drivers/gpu/drm/loongson/lsdc_output_7a1000.c index 6fc8dd1c7d9a..f331c198e3d4 100644 --- a/drivers/gpu/drm/loongson/lsdc_output_7a1000.c +++ b/drivers/gpu/drm/loongson/lsdc_output_7a1000.c @@ -140,11 +140,10 @@ static const struct drm_encoder_funcs ls7a1000_encoder_funcs[2] = { }; int ls7a1000_output_init(struct drm_device *ddev, - struct lsdc_display_pipe *dispipe, + struct lsdc_output *output, struct i2c_adapter *ddc, unsigned int index) { - struct lsdc_output *output = &dispipe->output; struct drm_encoder *encoder = &output->encoder; struct drm_connector *connector = &output->connector; int ret; diff --git a/drivers/gpu/drm/loongson/lsdc_output_7a2000.c b/drivers/gpu/drm/loongson/lsdc_output_7a2000.c index ce3dabec887e..a81852939d23 100644 --- a/drivers/gpu/drm/loongson/lsdc_output_7a2000.c +++ b/drivers/gpu/drm/loongson/lsdc_output_7a2000.c @@ -284,8 +284,7 @@ static int ls7a2000_hdmi_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct lsdc_output *output = encoder_to_lsdc_output(encoder); - struct lsdc_display_pipe *dispipe = output_to_display_pipe(output); - unsigned int index = dispipe->index; + unsigned int index = output->descp->pipe; struct drm_device *ddev = encoder->dev; struct lsdc_device *ldev = to_lsdc(ddev); struct hdmi_avi_infoframe infoframe; @@ -335,8 +334,7 @@ static void ls7a2000_hdmi_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct lsdc_output *output = encoder_to_lsdc_output(encoder); - struct lsdc_display_pipe *dispipe = output_to_display_pipe(output); - unsigned int index = dispipe->index; + unsigned int index = output->descp->pipe; struct drm_device *ddev = encoder->dev; struct lsdc_device *ldev = to_lsdc(ddev); u32 val; @@ -360,8 +358,7 @@ static void ls7a2000_hdmi_atomic_enable(struct drm_encoder *encoder, struct drm_device *ddev = encoder->dev; struct lsdc_device *ldev = to_lsdc(ddev); struct lsdc_output *output = encoder_to_lsdc_output(encoder); - struct lsdc_display_pipe *dispipe = output_to_display_pipe(output); - unsigned int index = dispipe->index; + unsigned int index = output->descp->pipe; u32 val; /* datasheet say it should larger than 48 */ @@ -482,8 +479,7 @@ static void ls7a2000_hdmi_atomic_mode_set(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct lsdc_output *output = encoder_to_lsdc_output(encoder); - struct lsdc_display_pipe *dispipe = output_to_display_pipe(output); - unsigned int index = dispipe->index; + unsigned int index = output->descp->pipe; struct drm_device *ddev = encoder->dev; struct lsdc_device *ldev = to_lsdc(ddev); struct drm_display_mode *mode = &crtc_state->mode; @@ -512,11 +508,10 @@ static const struct drm_encoder_helper_funcs ls7a2000_encoder_helper_funcs = { * writing hdmi register do no harms. */ int ls7a2000_output_init(struct drm_device *ddev, - struct lsdc_display_pipe *dispipe, + struct lsdc_output *output, struct i2c_adapter *ddc, unsigned int pipe) { - struct lsdc_output *output = &dispipe->output; struct drm_encoder *encoder = &output->encoder; struct drm_connector *connector = &output->connector; int ret; -- 2.34.1