uboot/drivers/video/exynos/exynos_mipi_dsi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Samsung Electronics
   3 *
   4 * Author: InKi Dae <inki.dae@samsung.com>
   5 * Author: Donghwa Lee <dh09.lee@samsung.com>
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <common.h>
  11#include <malloc.h>
  12#include <fdtdec.h>
  13#include <libfdt.h>
  14#include <linux/compat.h>
  15#include <linux/err.h>
  16#include <asm/arch/dsim.h>
  17#include <asm/arch/mipi_dsim.h>
  18#include <asm/arch/power.h>
  19#include <asm/arch/cpu.h>
  20#include <asm/arch/clk.h>
  21
  22#include "exynos_mipi_dsi_lowlevel.h"
  23#include "exynos_mipi_dsi_common.h"
  24
  25#define master_to_driver(a)     (a->dsim_lcd_drv)
  26#define master_to_device(a)     (a->dsim_lcd_dev)
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29
  30struct mipi_dsim_ddi {
  31        int                             bus_id;
  32        struct list_head                list;
  33        struct mipi_dsim_lcd_device     *dsim_lcd_dev;
  34        struct mipi_dsim_lcd_driver     *dsim_lcd_drv;
  35};
  36
  37static LIST_HEAD(dsim_ddi_list);
  38static LIST_HEAD(dsim_lcd_dev_list);
  39
  40int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
  41{
  42        struct mipi_dsim_ddi *dsim_ddi;
  43
  44        if (!lcd_dev) {
  45                debug("mipi_dsim_lcd_device is NULL.\n");
  46                return -EFAULT;
  47        }
  48
  49        if (!lcd_dev->name) {
  50                debug("dsim_lcd_device name is NULL.\n");
  51                return -EFAULT;
  52        }
  53
  54        dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
  55        if (!dsim_ddi) {
  56                debug("failed to allocate dsim_ddi object.\n");
  57                return -EFAULT;
  58        }
  59
  60        dsim_ddi->dsim_lcd_dev = lcd_dev;
  61
  62        list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
  63
  64        return 0;
  65}
  66
  67struct mipi_dsim_ddi
  68        *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
  69{
  70        struct mipi_dsim_ddi *dsim_ddi;
  71        struct mipi_dsim_lcd_device *lcd_dev;
  72
  73        list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
  74                lcd_dev = dsim_ddi->dsim_lcd_dev;
  75                if (!lcd_dev)
  76                        continue;
  77
  78                if (lcd_drv->id >= 0) {
  79                        if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0 &&
  80                                        lcd_drv->id == lcd_dev->id) {
  81                                /**
  82                                 * bus_id would be used to identify
  83                                 * connected bus.
  84                                 */
  85                                dsim_ddi->bus_id = lcd_dev->bus_id;
  86
  87                                return dsim_ddi;
  88                        }
  89                } else {
  90                        if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
  91                                /**
  92                                 * bus_id would be used to identify
  93                                 * connected bus.
  94                                 */
  95                                dsim_ddi->bus_id = lcd_dev->bus_id;
  96
  97                                return dsim_ddi;
  98                        }
  99                }
 100
 101                kfree(dsim_ddi);
 102                list_del(&dsim_ddi_list);
 103        }
 104
 105        return NULL;
 106}
 107
 108int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
 109{
 110        struct mipi_dsim_ddi *dsim_ddi;
 111
 112        if (!lcd_drv) {
 113                debug("mipi_dsim_lcd_driver is NULL.\n");
 114                return -EFAULT;
 115        }
 116
 117        if (!lcd_drv->name) {
 118                debug("dsim_lcd_driver name is NULL.\n");
 119                return -EFAULT;
 120        }
 121
 122        dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
 123        if (!dsim_ddi) {
 124                debug("mipi_dsim_ddi object not found.\n");
 125                return -EFAULT;
 126        }
 127
 128        dsim_ddi->dsim_lcd_drv = lcd_drv;
 129
 130        debug("registered panel driver(%s) to mipi-dsi driver.\n",
 131                lcd_drv->name);
 132
 133        return 0;
 134
 135}
 136
 137struct mipi_dsim_ddi
 138        *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
 139                        const char *name)
 140{
 141        struct mipi_dsim_ddi *dsim_ddi;
 142        struct mipi_dsim_lcd_driver *lcd_drv;
 143        struct mipi_dsim_lcd_device *lcd_dev;
 144
 145        list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
 146                lcd_drv = dsim_ddi->dsim_lcd_drv;
 147                lcd_dev = dsim_ddi->dsim_lcd_dev;
 148                if (!lcd_drv || !lcd_dev)
 149                        continue;
 150
 151                debug("lcd_drv->id = %d, lcd_dev->id = %d\n",
 152                                        lcd_drv->id, lcd_dev->id);
 153
 154                if ((strcmp(lcd_drv->name, name) == 0)) {
 155                        lcd_dev->master = dsim;
 156
 157                        dsim->dsim_lcd_dev = lcd_dev;
 158                        dsim->dsim_lcd_drv = lcd_drv;
 159
 160                        return dsim_ddi;
 161                }
 162        }
 163
 164        return NULL;
 165}
 166
 167/* define MIPI-DSI Master operations. */
 168static struct mipi_dsim_master_ops master_ops = {
 169        .cmd_write                      = exynos_mipi_dsi_wr_data,
 170        .get_dsim_frame_done            = exynos_mipi_dsi_get_frame_done_status,
 171        .clear_dsim_frame_done          = exynos_mipi_dsi_clear_frame_done,
 172};
 173
 174int exynos_mipi_dsi_init(struct exynos_platform_mipi_dsim *dsim_pd)
 175{
 176        struct mipi_dsim_device *dsim;
 177        struct mipi_dsim_config *dsim_config;
 178        struct mipi_dsim_ddi *dsim_ddi;
 179
 180        dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
 181        if (!dsim) {
 182                debug("failed to allocate dsim object.\n");
 183                return -EFAULT;
 184        }
 185
 186        /* get mipi_dsim_config. */
 187        dsim_config = dsim_pd->dsim_config;
 188        if (dsim_config == NULL) {
 189                debug("failed to get dsim config data.\n");
 190                return -EFAULT;
 191        }
 192
 193        dsim->pd = dsim_pd;
 194        dsim->dsim_config = dsim_config;
 195        dsim->master_ops = &master_ops;
 196
 197        /* bind lcd ddi matched with panel name. */
 198        dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
 199        if (!dsim_ddi) {
 200                debug("mipi_dsim_ddi object not found.\n");
 201                return -ENOSYS;
 202        }
 203        if (dsim_pd->lcd_power)
 204                dsim_pd->lcd_power();
 205
 206        if (dsim_pd->mipi_power)
 207                dsim_pd->mipi_power();
 208
 209        /* phy_enable(unsigned int dev_index, unsigned int enable) */
 210        if (dsim_pd->phy_enable)
 211                dsim_pd->phy_enable(0, 1);
 212
 213        set_mipi_clk();
 214
 215        exynos_mipi_dsi_init_dsim(dsim);
 216        exynos_mipi_dsi_init_link(dsim);
 217        exynos_mipi_dsi_set_hs_enable(dsim);
 218
 219        /* set display timing. */
 220        exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
 221
 222        /* initialize mipi-dsi client(lcd panel). */
 223        if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->mipi_panel_init) {
 224                dsim_ddi->dsim_lcd_drv->mipi_panel_init(dsim);
 225                dsim_ddi->dsim_lcd_drv->mipi_display_on(dsim);
 226        }
 227
 228        debug("mipi-dsi driver(%s mode) has been probed.\n",
 229                (dsim_config->e_interface == DSIM_COMMAND) ?
 230                        "CPU" : "RGB");
 231
 232        return 0;
 233}
 234
 235int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt,
 236                                struct mipi_dsim_lcd_device *lcd_dt)
 237{
 238        int node;
 239
 240        node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_MIPI_DSI);
 241        if (node <= 0) {
 242                printf("exynos_mipi_dsi: Can't get device node for mipi dsi\n");
 243                return -ENODEV;
 244        }
 245
 246        dt->e_interface = fdtdec_get_int(blob, node,
 247                                "samsung,dsim-config-e-interface", 0);
 248
 249        dt->e_virtual_ch = fdtdec_get_int(blob, node,
 250                                "samsung,dsim-config-e-virtual-ch", 0);
 251
 252        dt->e_pixel_format = fdtdec_get_int(blob, node,
 253                                "samsung,dsim-config-e-pixel-format", 0);
 254
 255        dt->e_burst_mode = fdtdec_get_int(blob, node,
 256                                "samsung,dsim-config-e-burst-mode", 0);
 257
 258        dt->e_no_data_lane = fdtdec_get_int(blob, node,
 259                                "samsung,dsim-config-e-no-data-lane", 0);
 260
 261        dt->e_byte_clk = fdtdec_get_int(blob, node,
 262                                "samsung,dsim-config-e-byte-clk", 0);
 263
 264        dt->hfp = fdtdec_get_int(blob, node,
 265                                "samsung,dsim-config-hfp", 0);
 266
 267        dt->p = fdtdec_get_int(blob, node,
 268                                          "samsung,dsim-config-p", 0);
 269        dt->m = fdtdec_get_int(blob, node,
 270                                          "samsung,dsim-config-m", 0);
 271        dt->s = fdtdec_get_int(blob, node,
 272                                          "samsung,dsim-config-s", 0);
 273
 274        dt->pll_stable_time = fdtdec_get_int(blob, node,
 275                                "samsung,dsim-config-pll-stable-time", 0);
 276
 277        dt->esc_clk = fdtdec_get_int(blob, node,
 278                                "samsung,dsim-config-esc-clk", 0);
 279
 280        dt->stop_holding_cnt = fdtdec_get_int(blob, node,
 281                                "samsung,dsim-config-stop-holding-cnt", 0);
 282
 283        dt->bta_timeout = fdtdec_get_int(blob, node,
 284                                "samsung,dsim-config-bta-timeout", 0);
 285
 286        dt->rx_timeout = fdtdec_get_int(blob, node,
 287                                "samsung,dsim-config-rx-timeout", 0);
 288
 289        lcd_dt->name = fdtdec_get_config_string(blob,
 290                                "samsung,dsim-device-name");
 291
 292        lcd_dt->id = fdtdec_get_int(blob, node,
 293                                "samsung,dsim-device-id", 0);
 294
 295        lcd_dt->bus_id = fdtdec_get_int(blob, node,
 296                                "samsung,dsim-device-bus_id", 0);
 297
 298        lcd_dt->reverse_panel = fdtdec_get_int(blob, node,
 299                                "samsung,dsim-device-reverse-panel", 0);
 300
 301        return 0;
 302}
 303
 304void exynos_init_dsim_platform_data(vidinfo_t *vid)
 305{
 306        static struct mipi_dsim_config dsim_config_dt;
 307        static struct exynos_platform_mipi_dsim dsim_platform_data_dt;
 308        static struct mipi_dsim_lcd_device mipi_lcd_device_dt;
 309
 310        if (exynos_dsim_config_parse_dt(gd->fdt_blob, &dsim_config_dt,
 311                                        &mipi_lcd_device_dt))
 312                debug("Can't get proper dsim config.\n");
 313
 314        strcpy(dsim_platform_data_dt.lcd_panel_name, mipi_lcd_device_dt.name);
 315        dsim_platform_data_dt.dsim_config = &dsim_config_dt;
 316        dsim_platform_data_dt.mipi_power = mipi_power;
 317        dsim_platform_data_dt.phy_enable = set_mipi_phy_ctrl;
 318        dsim_platform_data_dt.lcd_panel_info = (void *)vid;
 319
 320        mipi_lcd_device_dt.platform_data = (void *)&dsim_platform_data_dt;
 321        exynos_mipi_dsi_register_lcd_device(&mipi_lcd_device_dt);
 322
 323        vid->dsim_platform_data_dt = &dsim_platform_data_dt;
 324}
 325