Merge tag 'fbdev-updates-for-3.7' of git://github.com/schandinat/linux-2.6
[linux-2.6-microblaze.git] / drivers / video / omap2 / displays / panel-taal.c
index 6b5e6e0..f2f6446 100644 (file)
@@ -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;