diff options
Diffstat (limited to 'drivers/video/omap2/displays/panel-taal.c')
-rw-r--r-- | drivers/video/omap2/displays/panel-taal.c | 239 |
1 files changed, 127 insertions, 112 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 6b5e6e0e202f..f2f644680ca8 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -121,6 +121,18 @@ struct taal_data { struct omap_dss_device *dssdev; + /* panel specific HW info */ + struct panel_config *panel_config; + + /* panel HW configuration from DT or platform data */ + int reset_gpio; + int ext_te_gpio; + + bool use_dsi_backlight; + + struct omap_dsi_pin_config pin_config; + + /* runtime variables */ bool enabled; u8 rotate; bool mirror; @@ -145,16 +157,8 @@ struct taal_data { bool ulps_enabled; unsigned ulps_timeout; struct delayed_work ulps_work; - - struct panel_config *panel_config; }; -static inline struct nokia_dsi_panel_data -*get_panel_data(const struct omap_dss_device *dssdev) -{ - return (struct nokia_dsi_panel_data *) dssdev->data; -} - static void taal_esd_work(struct work_struct *work); static void taal_ulps_work(struct work_struct *work); @@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev) static int taal_enter_ulps(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); int r; if (td->ulps_enabled) @@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev) if (r) goto err; - disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); + if (gpio_is_valid(td->ext_te_gpio)) + disable_irq(gpio_to_irq(td->ext_te_gpio)); omapdss_dsi_display_disable(dssdev, false, true); @@ -405,7 +409,6 @@ err: static int taal_exit_ulps(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); int r; if (!td->ulps_enabled) @@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev) goto err2; } - enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); + if (gpio_is_valid(td->ext_te_gpio)) + enable_irq(gpio_to_irq(td->ext_te_gpio)); taal_queue_ulps_work(dssdev); @@ -438,7 +442,8 @@ err2: r = taal_panel_reset(dssdev); if (!r) { - enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); + if (gpio_is_valid(td->ext_te_gpio)) + enable_irq(gpio_to_irq(td->ext_te_gpio)); td->ulps_enabled = false; } err1: @@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = { static void taal_hw_reset(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); - if (panel_data->reset_gpio == -1) + if (!gpio_is_valid(td->reset_gpio)) return; - gpio_set_value(panel_data->reset_gpio, 1); + gpio_set_value(td->reset_gpio, 1); if (td->panel_config->reset_sequence.high) udelay(td->panel_config->reset_sequence.high); /* reset the panel */ - gpio_set_value(panel_data->reset_gpio, 0); + gpio_set_value(td->reset_gpio, 0); /* assert reset */ if (td->panel_config->reset_sequence.low) udelay(td->panel_config->reset_sequence.low); - gpio_set_value(panel_data->reset_gpio, 1); + gpio_set_value(td->reset_gpio, 1); /* wait after releasing reset */ if (td->panel_config->sleep.hw_reset) msleep(td->panel_config->sleep.hw_reset); } +static void taal_probe_pdata(struct taal_data *td, + const struct nokia_dsi_panel_data *pdata) +{ + td->reset_gpio = pdata->reset_gpio; + + if (pdata->use_ext_te) + td->ext_te_gpio = pdata->ext_te_gpio; + else + td->ext_te_gpio = -1; + + td->esd_interval = pdata->esd_interval; + td->ulps_timeout = pdata->ulps_timeout; + + td->use_dsi_backlight = pdata->use_dsi_backlight; + + td->pin_config = pdata->pin_config; +} + static int taal_probe(struct omap_dss_device *dssdev) { struct backlight_properties props; struct taal_data *td; struct backlight_device *bldev = NULL; - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); - struct panel_config *panel_config = NULL; int r, i; + const char *panel_name; dev_dbg(&dssdev->dev, "probe\n"); - if (!panel_data || !panel_data->name) { - r = -EINVAL; - goto err; + td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL); + if (!td) + return -ENOMEM; + + dev_set_drvdata(&dssdev->dev, td); + td->dssdev = dssdev; + + if (dssdev->data) { + const struct nokia_dsi_panel_data *pdata = dssdev->data; + + taal_probe_pdata(td, pdata); + + panel_name = pdata->name; + } else { + return -ENODEV; } + if (panel_name == NULL) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { - if (strcmp(panel_data->name, panel_configs[i].name) == 0) { - panel_config = &panel_configs[i]; + if (strcmp(panel_name, panel_configs[i].name) == 0) { + td->panel_config = &panel_configs[i]; break; } } - if (!panel_config) { - r = -EINVAL; - goto err; - } + if (!td->panel_config) + return -EINVAL; - dssdev->panel.timings = panel_config->timings; + dssdev->panel.timings = td->panel_config->timings; dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; - - td = kzalloc(sizeof(*td), GFP_KERNEL); - if (!td) { - r = -ENOMEM; - goto err; - } - td->dssdev = dssdev; - td->panel_config = panel_config; - td->esd_interval = panel_data->esd_interval; - td->ulps_enabled = false; - td->ulps_timeout = panel_data->ulps_timeout; + dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | + OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; mutex_init(&td->lock); atomic_set(&td->do_update, 0); - td->workqueue = create_singlethread_workqueue("taal_esd"); - if (td->workqueue == NULL) { - dev_err(&dssdev->dev, "can't create ESD workqueue\n"); - r = -ENOMEM; - goto err_wq; + if (gpio_is_valid(td->reset_gpio)) { + r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio, + GPIOF_OUT_INIT_LOW, "taal rst"); + if (r) { + dev_err(&dssdev->dev, "failed to request reset gpio\n"); + return r; + } } - INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work); - INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); - dev_set_drvdata(&dssdev->dev, td); + if (gpio_is_valid(td->ext_te_gpio)) { + r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio, + GPIOF_IN, "taal irq"); + if (r) { + dev_err(&dssdev->dev, "GPIO request failed\n"); + return r; + } + + r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio), + taal_te_isr, + IRQF_TRIGGER_RISING, + "taal vsync", dssdev); - if (gpio_is_valid(panel_data->reset_gpio)) { - r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW, - "taal rst"); if (r) { - dev_err(&dssdev->dev, "failed to request reset gpio\n"); - goto err_rst_gpio; + dev_err(&dssdev->dev, "IRQ request failed\n"); + return r; } + + INIT_DEFERRABLE_WORK(&td->te_timeout_work, + taal_te_timeout_work_callback); + + dev_dbg(&dssdev->dev, "Using GPIO TE\n"); } + td->workqueue = create_singlethread_workqueue("taal_esd"); + if (td->workqueue == NULL) { + dev_err(&dssdev->dev, "can't create ESD workqueue\n"); + return -ENOMEM; + } + INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work); + INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); + taal_hw_reset(dssdev); - if (panel_data->use_dsi_backlight) { + if (td->use_dsi_backlight) { memset(&props, 0, sizeof(struct backlight_properties)); props.max_brightness = 255; @@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev) taal_bl_update_status(bldev); } - if (panel_data->use_ext_te) { - int gpio = panel_data->ext_te_gpio; - - r = gpio_request_one(gpio, GPIOF_IN, "taal irq"); - if (r) { - dev_err(&dssdev->dev, "GPIO request failed\n"); - goto err_gpio; - } - - r = request_irq(gpio_to_irq(gpio), taal_te_isr, - IRQF_TRIGGER_RISING, - "taal vsync", dssdev); - - if (r) { - dev_err(&dssdev->dev, "IRQ request failed\n"); - gpio_free(gpio); - goto err_irq; - } - - INIT_DEFERRABLE_WORK(&td->te_timeout_work, - taal_te_timeout_work_callback); - - dev_dbg(&dssdev->dev, "Using GPIO TE\n"); - } - r = omap_dsi_request_vc(dssdev, &td->channel); if (r) { dev_err(&dssdev->dev, "failed to get virtual channel\n"); @@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev) err_vc_id: omap_dsi_release_vc(dssdev, td->channel); err_req_vc: - if (panel_data->use_ext_te) - free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); -err_irq: - if (panel_data->use_ext_te) - gpio_free(panel_data->ext_te_gpio); -err_gpio: if (bldev != NULL) backlight_device_unregister(bldev); err_bl: - if (gpio_is_valid(panel_data->reset_gpio)) - gpio_free(panel_data->reset_gpio); -err_rst_gpio: destroy_workqueue(td->workqueue); -err_wq: - kfree(td); -err: return r; } static void __exit taal_remove(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); struct backlight_device *bldev; dev_dbg(&dssdev->dev, "remove\n"); @@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); omap_dsi_release_vc(dssdev, td->channel); - if (panel_data->use_ext_te) { - int gpio = panel_data->ext_te_gpio; - free_irq(gpio_to_irq(gpio), dssdev); - gpio_free(gpio); - } - bldev = td->bldev; if (bldev != NULL) { bldev->props.power = FB_BLANK_POWERDOWN; @@ -1040,26 +1042,31 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) /* reset, to be sure that the panel is in a valid state */ taal_hw_reset(dssdev); - - if (gpio_is_valid(panel_data->reset_gpio)) - gpio_free(panel_data->reset_gpio); - - kfree(td); } static int taal_power_on(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); u8 id1, id2, id3; int r; - r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config); + r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); if (r) { dev_err(&dssdev->dev, "failed to configure DSI pins\n"); goto err0; }; + omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res, + dssdev->panel.timings.y_res); + omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888); + omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE); + + r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000); + if (r) { + dev_err(&dssdev->dev, "failed to set HS and LP clocks\n"); + goto err0; + } + r = omapdss_dsi_display_enable(dssdev); if (r) { dev_err(&dssdev->dev, "failed to enable DSI\n"); @@ -1356,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); int r; dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); @@ -1380,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev, if (r) goto err; - if (td->te_enabled && panel_data->use_ext_te) { + if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) { schedule_delayed_work(&td->te_timeout_work, msecs_to_jiffies(250)); atomic_set(&td->do_update, 1); @@ -1419,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev) static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); int r; if (enable) @@ -1427,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) else r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); - if (!panel_data->use_ext_te) + if (!gpio_is_valid(td->ext_te_gpio)) omapdss_dsi_enable_te(dssdev, enable); if (td->panel_config->sleep.enable_te) @@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev) static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u16 dw, dh; int r; dev_dbg(&dssdev->dev, "rotate %d\n", rotate); @@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) goto err; } + if (rotate == 0 || rotate == 2) { + dw = dssdev->panel.timings.x_res; + dh = dssdev->panel.timings.y_res; + } else { + dw = dssdev->panel.timings.y_res; + dh = dssdev->panel.timings.x_res; + } + + omapdss_dsi_set_size(dssdev, dw, dh); + td->rotate = rotate; dsi_bus_unlock(dssdev); @@ -1726,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work) struct taal_data *td = container_of(work, struct taal_data, esd_work.work); struct omap_dss_device *dssdev = td->dssdev; - struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); u8 state1, state2; int r; @@ -1773,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work) } /* Self-diagnostics result is also shown on TE GPIO line. We need * to re-enable TE after self diagnostics */ - if (td->te_enabled && panel_data->use_ext_te) { + if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) { r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); if (r) goto err; |