aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/samsung_duallcd/s5p-dsim.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/samsung_duallcd/s5p-dsim.c')
-rw-r--r--drivers/video/samsung_duallcd/s5p-dsim.c1597
1 files changed, 0 insertions, 1597 deletions
diff --git a/drivers/video/samsung_duallcd/s5p-dsim.c b/drivers/video/samsung_duallcd/s5p-dsim.c
deleted file mode 100644
index 05f4658..0000000
--- a/drivers/video/samsung_duallcd/s5p-dsim.c
+++ /dev/null
@@ -1,1597 +0,0 @@
-/* linux/drivers/video/samsung/s5p-dsim.c
- *
- * Samsung MIPI-DSIM driver.
- *
- * InKi Dae, <inki.dae@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Modified by Samsung Electronics (UK) on May 2010
- *
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/ctype.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/memory.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/workqueue.h>
-#include <linux/regulator/consumer.h>
-#include <linux/gpio.h>
-#include <plat/clock.h>
-#include <plat/regs-dsim.h>
-#include <plat/gpio-cfg.h>
-#include <mach/map.h>
-#include <mach/dsim.h>
-#include <mach/mipi_ddi.h>
-#include <mach/irqs.h>
-
-#include "s5p-dsim.h"
-#include "s5p_dsim_lowlevel.h"
-#include "s3cfb.h"
-
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#include <linux/earlysuspend.h>
-#include <linux/suspend.h>
-#endif
-
-struct mipi_lcd_info {
- struct list_head list;
- struct mipi_lcd_driver *mipi_drv;
-};
-
-static DEFINE_MUTEX(dsim_rd_wr_mutex);
-static DECLARE_COMPLETION(dsim_rd_comp);
-static DECLARE_COMPLETION(dsim_wr_comp);
-
-#define MIPI_RESP_ERR 0x02
-#define MIPI_RESP_EOTP 0x08
-#define MIPI_RESP_GENERIC_RD_1 0x11
-#define MIPI_RESP_GENERIC_RD_2 0x12
-#define MIPI_RESP_GENERIC_RD_LONG 0x1A
-#define MIPI_RESP_DCS_RD_LONG 0x1C
-#define MIPI_RESP_DCS_RD_1 0x21
-#define MIPI_RESP_DCS_RD_2 0x22
-
-#define MIPI_CMD_GENERIC_WR_0 0x03
-#define MIPI_CMD_GENERIC_WR_1 0x13
-#define MIPI_CMD_GENERIC_WR_2 0x23
-#define MIPI_CMD_GENERIC_WR_LONG 0x29
-
-#define MIPI_CMD_DSI_WR_0 0x05
-#define MIPI_CMD_DSI_WR_1 0x15
-#define MIPI_CMD_DSI_WR_LONG 0x39
-
-#define MIPI_CMD_GENERIC_RD_0 0x04
-#define MIPI_CMD_GENERIC_RD_1 0x14
-#define MIPI_CMD_GENERIC_RD_2 0x24
-
-#define MIPI_CMD_DSI_RD_0 0x06
-
-#define MIPI_CMD_DSI_SET_PKT_SZ 0x37
-
-#define DSIM_TIMEOUT msecs_to_jiffies(250)
-#define DSIM_RX_FIFO_READ_DONE 0x30800002
-#define DSIM_MAX_RX_FIFO 20
-
-#define S5P_DSIM_INT_SFR_FIFO_EMPTY 29
-#define S5P_DSIM_INT_BTA 25
-#define S5P_DSIM_INT_MSK_FRAME_DONE 24
-#define S5P_DSIM_INT_RX_TIMEOUT 21
-#define S5P_DSIM_INT_BTA_TIMEOUT 20
-#define S5P_DSIM_INT_RX_DONE 18
-#define S5P_DSIM_INT_RX_TE 17
-#define S5P_DSIM_INT_RX_ACK 16
-#define S5P_DSIM_INT_RX_ECC_ERR 15
-#define S5P_DSIM_IMT_RX_CRC_ERR 14
-
-static LIST_HEAD(lcd_info_list);
-static DEFINE_MUTEX(mipi_lock);
-static struct dsim_global *g_dsim;
-
-static struct s5p_platform_dsim *to_dsim_plat(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
-
- return (struct s5p_platform_dsim *)pdev->dev.platform_data;
-}
-
-static void s5p_dsim_frame_done_interrupt_enable(struct dsim_global *dsim, u8 enable)
-{
- u32 intmsk;
- u8 state = !enable;
-
- if (!dsim->mipi_ddi_pd->resume_complete)
- return;
-
- intmsk = readl(dsim->reg_base + S5P_DSIM_INTMSK);
-
- if (state == 0) /* enable Frame Done interrupts */
- intmsk &= ~(0x01 << S5P_DSIM_INT_MSK_FRAME_DONE);
- else /* disable Frame Done interrupts */
- intmsk |= (0x01 << S5P_DSIM_INT_MSK_FRAME_DONE);
-
- writel(intmsk, dsim->reg_base + S5P_DSIM_INTMSK);
-}
-
-void set_dsim_lcd_enabled(u8 enable)
-{
- struct dsim_global *dsim = g_dsim;
-
- dsim->dsim_lcd_info->lcd_enabled = enable;
- if (dsim->dsim_info->hs_toggle)
- s5p_dsim_frame_done_interrupt_enable(dsim, enable);
-}
-
-void set_dsim_hs_clk_toggle_count(u8 count)
-{
- struct dsim_global *dsim = g_dsim;
-
- dsim->dsim_toggle_per_frame_count = count;
- if (dsim->dsim_lcd_info->lcd_enabled)
- s5p_dsim_frame_done_interrupt_enable(dsim, count ? 1 : 0);
-}
-
-static void dsim_work_q_handler(struct work_struct *work)
-{
- struct dsim_global *dsim =
- container_of(work, struct dsim_global, dsim_work.work);
-
- s5p_dsim_frame_done_interrupt_enable(dsim, 1);
-}
-
-static void dsim_check_hs_toggle_work_q_handler(struct work_struct *work)
-{
- struct dsim_global *dsim =
- container_of(work, struct dsim_global, check_hs_toggle_work.work);
-
- if (dsim->dsim_info->hs_toggle) {
- dev_info(dsim->dev, "check_hs_toggle\n");
- schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(120000));
- }
-}
-
-unsigned char s5p_dsim_wr_data(void *ptr,
- unsigned int data_id, unsigned int data0, unsigned int data1)
-{
- struct dsim_global *dsim = ptr;
- unsigned int dsim_base = dsim->reg_base;
-
- if (dsim->state == DSIM_STATE_ULPS) {
- dev_err(dsim->dev, "DSIM state: ULPS\n");
- return DSIM_FALSE;
- }
-
- if (dsim->mipi_ddi_pd->resume_complete == 0) {
- dev_err(dsim->dev, "DSIM Status: SUSPEND\n");
- return DSIM_FALSE;
- }
-
- mutex_lock(&dsim_rd_wr_mutex);
-
- switch (data_id) {
- /* short packet types of packet types for command. */
- case GEN_SHORT_WR_NO_PARA:
- case GEN_SHORT_WR_1_PARA:
- case GEN_SHORT_WR_2_PARA:
- case DCS_WR_NO_PARA:
- case DCS_WR_1_PARA:
- case SET_MAX_RTN_PKT_SIZE:
- s5p_dsim_wr_tx_header(dsim_base, (unsigned char) data_id,
- (unsigned char) data0, (unsigned char) data1);
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_TRUE; /* response should be implemented */
- /* general command */
- case CMD_OFF:
- case CMD_ON:
- case SHUT_DOWN:
- case TURN_ON:
- s5p_dsim_wr_tx_header(dsim_base, (unsigned char) data_id,
- (unsigned char) data0, (unsigned char) data1);
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_TRUE; /* response should be implemented. */
- /* packet types for video data */
- case VSYNC_START:
- case VSYNC_END:
- case HSYNC_START:
- case HSYNC_END:
- case EOT_PKT:
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_TRUE;
-
- /* short and response packet types for command */
- case GEN_RD_1_PARA:
- case GEN_RD_2_PARA:
- case GEN_RD_NO_PARA:
- case DCS_RD_NO_PARA:
- s5p_dsim_clear_interrupt(dsim_base, 0xffffffff);
- s5p_dsim_wr_tx_header(dsim_base, (unsigned char) data_id,
- (unsigned char) data0, (unsigned char) data1);
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_FALSE; /* response should be implemented. */
-
- /* long packet type and null packet */
- case NULL_PKT:
- case BLANKING_PKT:
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_TRUE;
- case GEN_LONG_WR:
- case DCS_LONG_WR:
- {
- u32 uCnt = 0;
- u32* pWordPtr = (u32 *)data0;
- INIT_COMPLETION(dsim_wr_comp);
-
- do {
- s5p_dsim_wr_tx_data(dsim_base, pWordPtr[uCnt]);
- } while (((data1-1) / 4) > uCnt++);
-
- /* put data into header fifo */
- s5p_dsim_wr_tx_header(dsim_base, (unsigned char) data_id,
- (unsigned char) (((unsigned short) data1) & 0xff),
- (unsigned char) ((((unsigned short) data1) & 0xff00) >> 8));
-
- if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp, DSIM_TIMEOUT)) {
- dev_err(dsim->dev, "[DSIM:ERROR] %s Timeout\n", __func__);
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_FALSE;
- }
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_TRUE;
- }
- /* packet typo for video data */
- case RGB565_PACKED:
- case RGB666_PACKED:
- case RGB666_LOOSLY:
- case RGB888_PACKED:
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_TRUE; /* response should be implemented. */
- default:
- dev_warn(dsim->dev, "data id %x is not supported current DSI spec\n", data_id);
- mutex_unlock(&dsim_rd_wr_mutex);
- return DSIM_FALSE;
- }
-}
-
-int s5p_dsim_rd_data(void *ptr, u8 addr, u16 count, u8 *buf)
-{
- u32 i, temp;
- u8 response = 0;
- u16 rxsize;
- u32 txhd;
- u32 rxhd;
- int j;
- struct dsim_global *dsim = ptr;
- unsigned int reg_base = dsim->reg_base;
-
- if (dsim->mipi_ddi_pd->resume_complete == 0) {
- dev_err(dsim->dev, "DSIM Status: SUSPEND\n");
- return DSIM_FALSE;
- }
-
- mutex_lock(&dsim_rd_wr_mutex);
- INIT_COMPLETION(dsim_rd_comp);
-
- switch (count) {
- case 1:
-#if defined(CONFIG_FB_S5P_S6E63M0)
- response = MIPI_RESP_DCS_RD_1;
-#else
- response = MIPI_RESP_GENERIC_RD_1;
-#endif /* CONFIG_FB_S5P_S6E63M0 */
- break;
- case 2:
-#if defined(CONFIG_FB_S5P_S6E63M0)
- response = MIPI_RESP_DCS_RD_2;
-#else
- response = MIPI_RESP_GENERIC_RD_2;
-#endif /* CONFIG_FB_S5P_S6E63M0 */
- break;
- default:
- response = MIPI_RESP_GENERIC_RD_LONG;
- break;
- }
-
- /* set return packet size */
- txhd = MIPI_CMD_DSI_SET_PKT_SZ | count << 8;
-
- writel(txhd, reg_base + S5P_DSIM_PKTHDR);
-
- /* set address to read */
-#if defined(CONFIG_FB_S5P_S6E63M0)
- txhd = MIPI_CMD_DSI_RD_0 | addr << 8;
-#else
- txhd = MIPI_CMD_GENERIC_RD_1 | addr << 8;
-#endif /* CONFIG_FB_S5P_S6E63M0 */
-
- writel(txhd, reg_base + S5P_DSIM_PKTHDR);
-
- if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp, DSIM_TIMEOUT)) {
- dev_err(dsim->dev, "ERROR:%s timout\n", __func__);
- mutex_unlock(&dsim_rd_wr_mutex);
- return 0;
- }
-
- rxhd = readl(reg_base + S5P_DSIM_RXFIFO);
- dev_info(dsim->dev, "rxhd : %x\n", rxhd);
- if ((u8)(rxhd & 0xff) != response) {
- dev_err(dsim->dev, "[DSIM:ERROR]:%s wrong response rxhd : %x, response:%x\n"
- , __func__, rxhd, response);
- goto clear_rx_fifo;
- }
- /* for short packet */
- if (count <= 2) {
- for (i = 0; i < count; i++)
- buf[i] = (rxhd >> (8+(i*8))) & 0xff;
- rxsize = count;
- } else {
- /* for long packet */
- rxsize = (u16)((rxhd & 0x00ffff00) >> 8);
- dev_info(dsim->dev, "rcv size : %d\n", rxsize);
- if (rxsize != count) {
- dev_err(dsim->dev, "[DSIM:ERROR]:%s received data size mismatch received : %d, requested : %d\n",
- __func__, rxsize, count);
- goto clear_rx_fifo;
- }
-
- for (i = 0; i < rxsize>>2; i++) {
- temp = readl(reg_base + S5P_DSIM_RXFIFO);
- dev_info(dsim->dev, "pkt : %08x\n", temp);
- for (j = 0; j < 4; j++) {
- buf[(i*4)+j] = (u8)(temp>>(j*8))&0xff;
- /* printk("Value : %02x\n",(temp>>(j*8))&0xff); */
- }
- }
- if (rxsize % 4) {
- temp = readl(reg_base + S5P_DSIM_RXFIFO);
- dev_info(dsim->dev, "pkt-l : %08x\n", temp);
- for (j = 0; j < rxsize%4; j++) {
- buf[(i*4)+j] = (u8)(temp>>(j*8))&0xff;
- /* printk("Value : %02x\n",(temp>>(j*8))&0xff); */
- }
- }
- }
-
- temp = readl(reg_base + S5P_DSIM_RXFIFO);
-
-#if !defined(CONFIG_FB_S5P_S6E63M0)
- if (temp != DSIM_RX_FIFO_READ_DONE) {
- dev_warn(dsim->dev, "[DSIM:WARN]:%s Can't found RX FIFO READ DONE FLAG : %x\n", __func__, temp);
- goto clear_rx_fifo;
- }
-#endif
-
- mutex_unlock(&dsim_rd_wr_mutex);
- return rxsize;
-
-clear_rx_fifo:
- i = 0;
- while (1) {
- temp = readl(reg_base+S5P_DSIM_RXFIFO);
- if ((temp == DSIM_RX_FIFO_READ_DONE) || (i > DSIM_MAX_RX_FIFO))
- break;
- dev_info(dsim->dev, "[DSIM:INFO] : %s clear rx fifo : %08x\n", __func__, temp);
- i++;
- }
- dev_info(dsim->dev, "[DSIM:INFO] : %s done count : %d, temp : %08x\n", __func__, i, temp);
-
- mutex_unlock(&dsim_rd_wr_mutex);
- return 0;
-
-}
-
-static irqreturn_t s5p_dsim_isr(int irq, void *dev_id)
-{
- int i;
- unsigned int intsrc = 0;
- unsigned int intmsk = 0;
- struct dsim_global *dsim = NULL;
-
- dsim = (struct dsim_global *)dev_id;
- if (!dsim) {
- printk(KERN_ERR "%s:error:wrong parameter\n", __func__);
- return IRQ_HANDLED;
- }
-
- intsrc = readl(dsim->reg_base + S5P_DSIM_INTSRC);
- intmsk = readl(dsim->reg_base + S5P_DSIM_INTMSK);
-
- intmsk = ~(intmsk) & intsrc;
-
- for (i = 0; i < 32; i++) {
- if (intmsk & (0x01<<i)) {
- switch (i) {
- case S5P_DSIM_INT_BTA:
- /* printk("S5P_DSIM_INT_BTA\n"); */
- break;
- case S5P_DSIM_INT_RX_TIMEOUT:
- /* printk("S5P_DSIM_INT_RX_TIMEOUT\n"); */
- break;
- case S5P_DSIM_INT_BTA_TIMEOUT:
- /* printk("S5P_DSIM_INT_BTA_TIMEOUT\n"); */
- break;
- case S5P_DSIM_INT_RX_DONE:
- complete_all(&dsim_rd_comp);
- /* printk("S5P_DSIM_INT_RX_DONE\n"); */
- break;
- case S5P_DSIM_INT_RX_TE:
- /* printk("S5P_DSIM_INT_RX_TE\n"); */
- break;
- case S5P_DSIM_INT_RX_ACK:
- /* printk("S5P_DSIM_INT_RX_ACK\n"); */
- break;
- case S5P_DSIM_INT_RX_ECC_ERR:
- /* printk("S5P_DSIM_INT_RX_ECC_ERR\n"); */
- break;
- case S5P_DSIM_IMT_RX_CRC_ERR:
- /* printk("S5P_DSIM_IMT_RX_CRC_ERR\n"); */
- break;
- case S5P_DSIM_INT_SFR_FIFO_EMPTY:
- /* printk("S5P_DSIM_INT_SFR_FIFO_EMPTY\n"); */
- complete_all(&dsim_wr_comp);
- break;
- case S5P_DSIM_INT_MSK_FRAME_DONE:
- /* printk("S5P_DSIM_INT_MSK_FRAME_DONE\n"); */
- if (dsim->dsim_lcd_info->lcd_enabled && dsim->mipi_ddi_pd->resume_complete) {
- if (completion_done(&dsim_wr_comp) && completion_done(&dsim_rd_comp)) {
- if (s3cfb_vsync_status_check()) {
- s5p_dsim_toggle_hs_clock(dsim->reg_base);
- if (!dsim->dsim_toggle_per_frame_count) {
- s5p_dsim_frame_done_interrupt_enable(dsim, 0);
- if (likely(dsim->dsim_info->hs_toggle - 1))
- schedule_delayed_work(&dsim->dsim_work, dsim->dsim_info->hs_toggle);
- }
- if (dsim->dsim_toggle_per_frame_count)
- dsim->dsim_toggle_per_frame_count--;
- }
- }
- }
- break;
- }
- }
- }
- /* clear irq */
- writel(intsrc, dsim->reg_base + S5P_DSIM_INTSRC);
- return IRQ_HANDLED;
-}
-
-static void s5p_dsim_init_header_fifo(struct dsim_global *dsim)
-{
- unsigned int cnt;
-
- for (cnt = 0; cnt < DSIM_HEADER_FIFO_SZ; cnt++)
- dsim->header_fifo_index[cnt] = -1;
- return;
-}
-
-static unsigned char s5p_dsim_pll_on(unsigned int dsim_base, unsigned char enable)
-{
- if (enable) {
- int sw_timeout = 1000;
- s5p_dsim_clear_interrupt(dsim_base, DSIM_PLL_STABLE);
- s5p_dsim_enable_pll(dsim_base, 1);
- while (1) {
- sw_timeout--;
- if (s5p_dsim_is_pll_stable(dsim_base))
- return DSIM_TRUE;
- if (sw_timeout == 0)
- return DSIM_FALSE;
- }
- } else
- s5p_dsim_enable_pll(dsim_base, 0);
-
- return DSIM_TRUE;
-}
-
-static unsigned long s5p_dsim_change_pll(struct dsim_global *dsim, unsigned char pre_divider,
- unsigned short main_divider, unsigned char scaler)
-{
- unsigned long dfin_pll, dfvco, dpll_out;
- unsigned char freq_band;
- unsigned char temp0 = 0, temp1 = 0;
- unsigned int dsim_base = dsim->reg_base;
-
- dfin_pll = (MIPI_FIN / pre_divider);
-
- if (dfin_pll < 6 * 1000 * 1000 || dfin_pll > 12 * 1000 * 1000) {
- dev_warn(dsim->dev, "warning!!\n");
- dev_warn(dsim->dev, "fin_pll range is 6MHz ~ 12MHz\n");
- dev_warn(dsim->dev, "fin_pll of mipi dphy pll is %luMHz\n", (dfin_pll / 1000000));
-
- s5p_dsim_enable_afc(dsim_base, 0, 0);
- } else {
- if (dfin_pll < 7 * 1000000)
- s5p_dsim_enable_afc(dsim_base, 1, 0x1);
- else if (dfin_pll < 8 * 1000000)
- s5p_dsim_enable_afc(dsim_base, 1, 0x0);
- else if (dfin_pll < 9 * 1000000)
- s5p_dsim_enable_afc(dsim_base, 1, 0x3);
- else if (dfin_pll < 10 * 1000000)
- s5p_dsim_enable_afc(dsim_base, 1, 0x2);
- else if (dfin_pll < 11 * 1000000)
- s5p_dsim_enable_afc(dsim_base, 1, 0x5);
- else
- s5p_dsim_enable_afc(dsim_base, 1, 0x4);
- }
-
- dfvco = dfin_pll * main_divider;
- dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n",
- dfvco, dfin_pll, main_divider);
- if (dfvco < 500000000 || dfvco > 1000000000) {
- dev_warn(dsim->dev, "Caution!!\n");
- dev_warn(dsim->dev, "fvco range is 500MHz ~ 1000MHz\n");
- dev_warn(dsim->dev, "fvco of mipi dphy pll is %luMHz\n", (dfvco / 1000000));
- }
-
- dpll_out = dfvco / (1 << scaler);
- dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n",
- dpll_out, dfvco, scaler);
- if (dpll_out < 100 * 1000000)
- freq_band = 0x0;
- else if (dpll_out < 120 * 1000000)
- freq_band = 0x1;
- else if (dpll_out < 170 * 1000000)
- freq_band = 0x2;
- else if (dpll_out < 220 * 1000000)
- freq_band = 0x3;
- else if (dpll_out < 270 * 1000000)
- freq_band = 0x4;
- else if (dpll_out < 320 * 1000000)
- freq_band = 0x5;
- else if (dpll_out < 390 * 1000000)
- freq_band = 0x6;
- else if (dpll_out < 450 * 1000000)
- freq_band = 0x7;
- else if (dpll_out < 510 * 1000000)
- freq_band = 0x8;
- else if (dpll_out < 560 * 1000000)
- freq_band = 0x9;
- else if (dpll_out < 640 * 1000000)
- freq_band = 0xa;
- else if (dpll_out < 690 * 1000000)
- freq_band = 0xb;
- else if (dpll_out < 770 * 1000000)
- freq_band = 0xc;
- else if (dpll_out < 870 * 1000000)
- freq_band = 0xd;
- else if (dpll_out < 950 * 1000000)
- freq_band = 0xe;
- else
- freq_band = 0xf;
-
- dev_dbg(dsim->dev, "freq_band = %d\n", freq_band);
-
- s5p_dsim_pll_freq(dsim_base, pre_divider, main_divider, scaler);
-
- s5p_dsim_hs_zero_ctrl(dsim_base, temp0);
- s5p_dsim_prep_ctrl(dsim_base, temp1);
-
- /* Freq Band */
- s5p_dsim_pll_freq_band(dsim_base, freq_band);
-
- /* Stable time */
- s5p_dsim_pll_stable_time(dsim_base, dsim->dsim_info->pll_stable_time);
-
- /* Enable PLL */
- dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n", (dpll_out / 1000000));
-
- return dpll_out;
-}
-
-static void s5p_dsim_set_clock(struct dsim_global *dsim,
- unsigned char byte_clk_sel, unsigned char enable)
-{
- unsigned int esc_div;
- unsigned long esc_clk_error_rate;
- unsigned int dsim_base = dsim->reg_base;
-
- if (enable) {
- dsim->e_clk_src = byte_clk_sel;
-
- /* Escape mode clock and byte clock source */
- s5p_dsim_set_byte_clock_src(dsim_base, byte_clk_sel);
-
- /* DPHY, DSIM Link : D-PHY clock out */
- if (byte_clk_sel == DSIM_PLL_OUT_DIV8) {
- dsim->hs_clk = s5p_dsim_change_pll(dsim, dsim->dsim_info->p,
- dsim->dsim_info->m, dsim->dsim_info->s);
- dsim->byte_clk = dsim->hs_clk / 8;
- s5p_dsim_enable_pll_bypass(dsim_base, 0);
- s5p_dsim_pll_on(dsim_base, 1);
- usleep_range(1000, 1000);
- /* DPHY : D-PHY clock out, DSIM link : external clock out */
- } else if (byte_clk_sel == DSIM_EXT_CLK_DIV8)
- dev_warn(dsim->dev, "this project is not supported external clock source for MIPI DSIM\n");
- else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS)
- dev_warn(dsim->dev, "this project is not supported external clock source for MIPI DSIM\n");
-
- /* escape clock divider */
- esc_div = dsim->byte_clk / (dsim->dsim_info->esc_clk);
- dev_dbg(dsim->dev, "esc_div = %d, byte_clk = %lu, esc_clk = %lu\n",
- esc_div, dsim->byte_clk, dsim->dsim_info->esc_clk);
- if ((dsim->byte_clk / esc_div) >= 20000000 ||
- (dsim->byte_clk / esc_div) > dsim->dsim_info->esc_clk)
- esc_div += 1;
-
- dsim->escape_clk = dsim->byte_clk / esc_div;
- dev_dbg(dsim->dev, "escape_clk = %lu, byte_clk = %lu, esc_div = %d\n",
- dsim->escape_clk, dsim->byte_clk, esc_div);
-
- /*
- * enable escclk on lane
- */
- s5p_dsim_enable_byte_clock(dsim_base, DSIM_TRUE);
-
- /* enable byte clk and escape clock */
- s5p_dsim_set_esc_clk_prs(dsim_base, 1, esc_div);
- /* escape clock on lane */
- s5p_dsim_enable_esc_clk_on_lane(dsim_base, (DSIM_LANE_CLOCK | dsim->data_lane), 1);
-
- dev_dbg(dsim->dev, "byte clock is %luMHz\n", (dsim->byte_clk / 1000000));
- dev_dbg(dsim->dev, "escape clock that user's need is %lu\n", (dsim->dsim_info->esc_clk / 1000000));
- dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div);
- dev_dbg(dsim->dev, "escape clock is %luMHz\n", ((dsim->byte_clk / esc_div) / 1000000));
-
- if ((dsim->byte_clk / esc_div) > dsim->escape_clk) {
- esc_clk_error_rate = dsim->escape_clk / (dsim->byte_clk / esc_div);
- dev_warn(dsim->dev, "error rate is %lu over\n", (esc_clk_error_rate / 100));
- } else if ((dsim->byte_clk / esc_div) < (dsim->escape_clk)) {
- esc_clk_error_rate = (dsim->byte_clk / esc_div) / dsim->escape_clk;
- dev_warn(dsim->dev, "error rate is %lu under\n", (esc_clk_error_rate / 100));
- }
- } else {
- s5p_dsim_enable_esc_clk_on_lane(dsim_base, (DSIM_LANE_CLOCK | dsim->data_lane), 0);
- s5p_dsim_set_esc_clk_prs(dsim_base, 0, 0);
-
- s5p_dsim_enable_byte_clock(dsim_base, DSIM_FALSE);
-
- if (byte_clk_sel == DSIM_PLL_OUT_DIV8)
- s5p_dsim_pll_on(dsim_base, 0);
- }
-}
-
-static int s5p_dsim_late_resume_init_dsim(struct dsim_global *dsim)
-{
- unsigned int dsim_base = dsim->reg_base;
-
- if (dsim->pd->init_d_phy)
- dsim->pd->init_d_phy(dsim->reg_base);
-
- dsim->state = DSIM_STATE_RESET;
-
- switch (dsim->dsim_info->e_no_data_lane) {
- case DSIM_DATA_LANE_1:
- dsim->data_lane = DSIM_LANE_DATA0;
- break;
- case DSIM_DATA_LANE_2:
- dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
- break;
- case DSIM_DATA_LANE_3:
- dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
- DSIM_LANE_DATA2;
- break;
- case DSIM_DATA_LANE_4:
- dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
- DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
- break;
- default:
- dev_info(dsim->dev, "data lane is invalid\n");
- return -1;
- };
-
- s5p_dsim_init_header_fifo(dsim);
- s5p_dsim_sw_reset(dsim_base);
- s5p_dsim_dp_dn_swap(dsim_base, dsim->dsim_info->e_lane_swap);
-
- /* enable only frame done interrupt */
- /* s5p_dsim_clear_interrupt(dsim_base, AllDsimIntr); */
- /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 1); */
-
- return 0;
-}
-
-#if 0
-static int s5p_dsim_init_dsim(struct dsim_global *dsim)
-{
- unsigned int dsim_base = dsim->reg_base;
-
- if (dsim->pd->init_d_phy)
- dsim->pd->init_d_phy(dsim->reg_base);
-
- dsim->state = DSIM_STATE_RESET;
-
- switch (dsim->dsim_info->e_no_data_lane) {
- case DSIM_DATA_LANE_1:
- dsim->data_lane = DSIM_LANE_DATA0;
- break;
- case DSIM_DATA_LANE_2:
- dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
- break;
- case DSIM_DATA_LANE_3:
- dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
- DSIM_LANE_DATA2;
- break;
- case DSIM_DATA_LANE_4:
- dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
- DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
- break;
- default:
- dev_info(dsim->dev, "data lane is invalid\n");
- return -1;
- };
-
- s5p_dsim_init_header_fifo(dsim);
- s5p_dsim_dp_dn_swap(dsim_base, dsim->dsim_info->e_lane_swap);
-
- /* enable only frame done interrupt */
- /* s5p_dsim_clear_interrupt(dsim_base, AllDsimIntr); */
- /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 1); */
-
- return 0;
-}
-#endif
-
-static void s5p_dsim_set_display_mode(struct dsim_global *dsim,
- struct dsim_lcd_config *main_lcd, struct dsim_lcd_config *sub_lcd)
-{
- struct s3cfb_lcd *main_lcd_panel_info = NULL, *sub_lcd_panel_info = NULL;
- struct s3cfb_lcd_timing *main_timing = NULL;
- unsigned int dsim_base = dsim->reg_base;
-
- if (main_lcd != NULL) {
- if (main_lcd->lcd_panel_info != NULL) {
- main_lcd_panel_info =
- (struct s3cfb_lcd *) main_lcd->lcd_panel_info;
-
- s5p_dsim_set_main_disp_resol(dsim_base,
- main_lcd_panel_info->height,
- main_lcd_panel_info->width);
- } else
- dev_warn(dsim->dev, "lcd panel info of main lcd is NULL\n");
- } else {
- dev_err(dsim->dev, "main lcd is NULL\n");
- return;
- }
-
- /* in case of VIDEO MODE (RGB INTERFACE) */
- if (dsim->dsim_lcd_info->e_interface == (u32)DSIM_VIDEO) {
-
- main_timing = &main_lcd_panel_info->timing;
- if (main_timing == NULL) {
- dev_err(dsim->dev, "main_timing is NULL\n");
- return;
- }
-
- s5p_dsim_set_main_disp_vporch(dsim_base,
- main_timing->cmd_allow_len,
- main_timing->stable_vfp, (u16) main_timing->v_bp);
- s5p_dsim_set_main_disp_hporch(dsim_base,
- main_timing->h_fp, (u16) main_timing->h_bp);
- s5p_dsim_set_main_disp_sync_area(dsim_base,
- main_timing->v_sw, (u16) main_timing->h_sw);
-
- /* in case of COMMAND MODE (CPU or I80 INTERFACE) */
- } else {
- if (sub_lcd != NULL) {
- if (sub_lcd->lcd_panel_info != NULL) {
- sub_lcd_panel_info =
- (struct s3cfb_lcd *)
- sub_lcd->lcd_panel_info;
-
- s5p_dsim_set_sub_disp_resol(dsim_base,
- sub_lcd_panel_info->height,
- sub_lcd_panel_info->width);
- } else
- dev_warn(dsim->dev, "lcd panel info of sub lcd is NULL\n");
- }
- }
-
- s5p_dsim_display_config(dsim_base, dsim->dsim_lcd_info, NULL);
-}
-
-static int s5p_dsim_init_link(struct dsim_global *dsim)
-{
- unsigned int time_out = 100;
- unsigned int dsim_base = dsim->reg_base;
-
- switch (dsim->state) {
- case DSIM_STATE_RESET:
- case DSIM_STATE_INIT:
- s5p_dsim_init_fifo_pointer(dsim_base, 0x0);
- usleep_range(10000, 10000);
- s5p_dsim_init_fifo_pointer(dsim_base, 0x1f);
-
- /* dsi configuration */
- s5p_dsim_init_config(dsim_base, dsim->dsim_lcd_info, NULL, dsim->dsim_info);
- s5p_dsim_enable_lane(dsim_base, DSIM_LANE_CLOCK, 1);
- s5p_dsim_enable_lane(dsim_base, dsim->data_lane, 1);
-
- /* set clock configuration */
- s5p_dsim_set_clock(dsim, dsim->dsim_info->e_byte_clk, 1);
- usleep_range(5000, 5000);
- /* check clock and data lane state is stop state */
- while (!(s5p_dsim_is_lane_state(dsim_base, DSIM_LANE_CLOCK) == DSIM_LANE_STATE_STOP) &&
- !(s5p_dsim_is_lane_state(dsim_base, dsim->data_lane) == DSIM_LANE_STATE_STOP)) {
- time_out--;
- if (time_out == 0) {
- dev_info(dsim->dev, "DSI Master state is not stop state!!!\n");
- dev_info(dsim->dev, "Please check initialization process\n");
-
- return DSIM_FALSE;
- }
- }
-
- if (time_out != 0) {
- /* dev_info(dsim->dev, "initialization of DSI Master is successful\n"); */
- /* dev_info(dsim->dev, "DSI Master state is stop state\n"); */
- }
-
- dsim->state = DSIM_STATE_STOP;
-
- /* BTA sequence counters */
- s5p_dsim_set_stop_state_counter(dsim_base, dsim->dsim_info->stop_holding_cnt);
- s5p_dsim_set_bta_timeout(dsim_base, dsim->dsim_info->bta_timeout);
- s5p_dsim_set_lpdr_timeout(dsim_base, dsim->dsim_info->rx_timeout);
-
- /* default LPDT by both cpu and lcd controller */
- s5p_dsim_set_data_mode(dsim_base, DSIM_TRANSFER_BOTH, DSIM_STATE_STOP);
-
- return DSIM_TRUE;
- default:
- dev_info(dsim->dev, "DSI Master is already init\n");
-
- return DSIM_FALSE;
- }
-}
-
-static unsigned char s5p_dsim_set_hs_enable(struct dsim_global *dsim)
-{
- u8 ret = DSIM_FALSE;
- unsigned int dsim_base = dsim->reg_base;
-
- if (dsim->state == DSIM_STATE_STOP) {
- if (dsim->e_clk_src != DSIM_EXT_CLK_BYPASS) {
- dsim->state = DSIM_STATE_HSCLKEN;
-#if defined(CONFIG_FB_S5P_S6E63M0)
- s5p_dsim_set_data_mode(dsim_base,
- DSIM_TRANSFER_BYLCDC, DSIM_STATE_HSCLKEN);
-#else
- s5p_dsim_set_data_mode(dsim_base,
- DSIM_TRANSFER_BOTH, DSIM_STATE_HSCLKEN);
-#endif
- s5p_dsim_enable_hs_clock(dsim_base, 1);
-
- ret = DSIM_TRUE;
- } else
- dev_warn(dsim->dev, "clock source is external bypass\n");
- } else
- dev_warn(dsim->dev, "DSIM is not stop state\n");
-
- return ret;
-}
-
-#if 0
-static unsigned char s5p_dsim_set_stopstate(struct dsim_global *dsim)
-{
- u8 ret = DSIM_FALSE;
- unsigned int dsim_base = dsim->reg_base;
-
- if (dsim->state == DSIM_STATE_HSCLKEN) {
- if (dsim->e_clk_src != DSIM_EXT_CLK_BYPASS) {
- dsim->state = DSIM_STATE_STOP;
- s5p_dsim_enable_hs_clock(dsim_base, 0);
- ret = DSIM_TRUE;
- } else
- dev_warn(dsim->dev, "clock source is external bypass\n");
- } else if (dsim->state == DSIM_STATE_ULPS) {
- /* will be update for exiting ulps */
- ret = DSIM_TRUE;
- } else if (dsim->state == DSIM_STATE_STOP) {
- dev_warn(dsim->dev, "DSIM is already stop state\n");
- ret = DSIM_TRUE;
- } else
- dev_warn(dsim->dev, "DSIM is not stop state\n");
-
- return ret;
-}
-#endif
-
-static unsigned char s5p_dsim_set_data_transfer_mode(struct dsim_global *dsim,
- unsigned char data_path, unsigned char hs_enable)
-{
- u8 ret = DSIM_FALSE;
- unsigned int dsim_base = dsim->reg_base;
-
- if (hs_enable) {
- if (dsim->state == DSIM_STATE_HSCLKEN) {
- s5p_dsim_set_data_mode(dsim_base, data_path, DSIM_STATE_HSCLKEN);
- ret = DSIM_TRUE;
- } else {
- dev_err(dsim->dev, "HS Clock lane is not enabled\n");
- ret = DSIM_FALSE;
- }
- } else {
- if (dsim->state == DSIM_STATE_INIT || dsim->state == DSIM_STATE_ULPS) {
- dev_err(dsim->dev, "DSI Master is not STOP or HSDT state\n");
- ret = DSIM_FALSE;
- } else {
- s5p_dsim_set_data_mode(dsim_base, data_path, DSIM_STATE_STOP);
- ret = DSIM_TRUE;
- }
- }
-
- return ret;
-}
-
-int s5p_dsim_register_lcd_driver(struct mipi_lcd_driver *lcd_drv)
-{
- struct mipi_lcd_info *lcd_info = NULL;
- struct dsim_global *dsim = g_dsim;
-
- lcd_info = kmalloc(sizeof(struct mipi_lcd_info), GFP_KERNEL);
- if (lcd_info == NULL)
- return -ENOMEM;
-
- lcd_info->mipi_drv = kmalloc(sizeof(struct mipi_lcd_driver), GFP_KERNEL);
- if (lcd_info->mipi_drv == NULL) {
- kfree(lcd_info);
- return -ENOMEM;
- }
-
- memcpy(lcd_info->mipi_drv, lcd_drv, sizeof(struct mipi_lcd_driver));
-
- mutex_lock(&mipi_lock);
- list_add_tail(&lcd_info->list, &lcd_info_list);
- mutex_unlock(&mipi_lock);
-
- dev_dbg(dsim->dev, "registered lcd panel driver(%s) to mipi-dsi driver\n", lcd_drv->name);
-
- return 0;
-}
-
-static struct mipi_lcd_driver *scan_mipi_driver(struct dsim_global *dsim, const char *name)
-{
- struct mipi_lcd_info *lcd_info;
- struct mipi_lcd_driver *mipi_drv = NULL;
-
- mutex_lock(&mipi_lock);
-
- dev_dbg(dsim->dev, "find lcd panel driver(%s)\n", name);
-
- list_for_each_entry(lcd_info, &lcd_info_list, list) {
- mipi_drv = lcd_info->mipi_drv;
-
- if ((strcmp(mipi_drv->name, name)) == 0) {
- mutex_unlock(&mipi_lock);
- dev_dbg(dsim->dev, "found!!!(%s)\n", mipi_drv->name);
- return mipi_drv;
- }
- }
-
- dev_warn(dsim->dev, "failed to find lcd panel driver(%s)\n", name);
-
- mutex_unlock(&mipi_lock);
-
- return NULL;
-}
-
-static void s5p_dsim_interrupt_mask_set(struct dsim_global *dsim)
-{
- u32 int_stat;
-
- int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK);
-
- int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) |
- (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) |
- (0x01<<S5P_DSIM_INT_RX_TE) | (0x01<<S5P_DSIM_INT_RX_ACK) |
- (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) |
- (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY));
-
- writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK);
-}
-
-int s5p_dsim_fifo_clear(void)
-{
- int dsim_count = 0, ret;
- struct dsim_global *dsim = g_dsim;
-
- writel(SwRstRelease, dsim->reg_base + S5P_DSIM_INTSRC);
-
- writel(DSIM_FUNCRST, dsim->reg_base + S5P_DSIM_SWRST);
-
- do {
- if (++dsim_count > 90000) {
- dev_err(dsim->dev, "dsim fifo clear fail re_try dsim resume\n");
- ret = 0;
- break;
- }
-
- if (readl(dsim->reg_base + S5P_DSIM_INTSRC) & SwRstRelease) {
- s5p_dsim_interrupt_mask_set(dsim);
- ret = 1;
- break;
- }
- } while (1);
-
- return ret;
-}
-
-#if defined(CONFIG_S5P_DSIM_SWITCHABLE_DUAL_LCD)
-int s5p_dsim_get_panel_sel_value(void)
-{
- /*Temporary provided*/
- struct dsim_global *dsim = g_dsim;
- unsigned int lcd_sel_pin = dsim->mipi_ddi_pd->lcd_sel_pin;
- int sel;
-
- if (!lcd_sel_pin) {
- printk(KERN_ERR "lcd_sel_pin is NULL\n");
- return -EINVAL;
- }
- sel = gpio_get_value(lcd_sel_pin);
- dsim->panel_select = sel;
-
- return sel;
- /*Temporary provided*/
-}
-
-int s5p_dsim_get_lcd_sel_value(void)
-{
- struct dsim_global *dsim = g_dsim;
- unsigned int lcd_sel_pin = dsim->mipi_ddi_pd->lcd_sel_pin;
- int sel;
-
- if (!lcd_sel_pin) {
- printk(KERN_ERR "lcd_sel_pin is NULL\n");
- return -EINVAL;
- }
- sel = gpio_get_value(lcd_sel_pin);
- dsim->panel_select = sel;
-
- return sel;
-}
-
-int s5p_dsim_set_lcd_sel_value(unsigned int lcd_sel)
-{
- struct dsim_global *dsim = g_dsim;
- unsigned int lcd_sel_pin = dsim->mipi_ddi_pd->lcd_sel_pin;
- int prev_lcd_sel = s5p_dsim_get_lcd_sel_value();
-
- if (!lcd_sel_pin) {
- printk(KERN_ERR "lcd_sel_pin is NULL\n");
- return -EINVAL;
- }
-
- gpio_set_value(lcd_sel_pin, lcd_sel);
- return prev_lcd_sel;
-}
-
-int s5p_dsim_toggle_lcd(void)
-{
- struct dsim_global *dsim = g_dsim;
- int prev_lcd_sel = s5p_dsim_get_lcd_sel_value();
- int new_lcd_sel = prev_lcd_sel ^ 1;
-
- if (prev_lcd_sel < 0) {
- printk(KERN_ERR "previous lcd sel value is invalid\n");
- return -EINVAL;
- }
-
- prev_lcd_sel = s5p_dsim_set_lcd_sel_value(new_lcd_sel);
- if (dsim->mipi_ddi_pd->resume_complete) {
- if (s5p_dsim_fifo_clear() == 0) {
- s5p_dsim_early_suspend();
- mdelay(10);
- s5p_dsim_late_resume();
- if (s5p_dsim_fifo_clear() == 0)
- printk(KERN_ERR "dsim resume fail!!\n");
- }
- mdelay(10);
- }
- return 0;
-}
-
-int s5p_dsim_select_lcd(unsigned int lcd_sel)
-{
- struct dsim_global *dsim = g_dsim;
- int prev_lcd_sel;
-
- if ((lcd_sel != DDI_MAIN_LCD) &&
- (lcd_sel != DDI_SUB_LCD)) {
- printk(KERN_ERR "lcd_sel(%d) is invalid value\n", lcd_sel);
- return -EINVAL;
- }
- prev_lcd_sel = s5p_dsim_set_lcd_sel_value(lcd_sel);
- if (dsim->mipi_ddi_pd->resume_complete) {
- if (s5p_dsim_fifo_clear() == 0) {
- s5p_dsim_early_suspend();
- mdelay(10);
- s5p_dsim_late_resume();
- if (s5p_dsim_fifo_clear() == 0)
- printk(KERN_ERR "dsim resume fail!!\n");
- }
- mdelay(10);
- }
- return 0;
-}
-#endif /* CONFIG_S5P_DSIM_SWITCHABLE_DUAL_LCD */
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-void s5p_dsim_early_suspend(void)
-{
- u32 int_stat = 0;
- pm_message_t state;
- struct dsim_global *dsim = g_dsim;
-
- dev_info(dsim->dev, "+%s\n", __func__);
-
- if (dsim->mipi_ddi_pd->resume_complete == 0)
- return;
-
- dsim->mipi_ddi_pd->resume_complete = 0;
- dsim->dsim_lcd_info->lcd_enabled = 0;
-
- /* int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); */
-
- int_stat |= ((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) |
- (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) |
- (0x01<<S5P_DSIM_INT_RX_TE) | (0x01<<S5P_DSIM_INT_RX_ACK) |
- (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) |
- (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY) | (0x01 << S5P_DSIM_INT_MSK_FRAME_DONE));
-
- writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK);
-
- /* disable_irq(dsim->irq); */
- state.event = PM_EVENT_SUSPEND;
-
- if (dsim->mipi_drv->suspend)
- dsim->mipi_drv->suspend(dsim->dev, state);
-
- if (dsim->mipi_ddi_pd->lcd_power_on)
- dsim->mipi_ddi_pd->lcd_power_on(dsim->dev, 0);
-
- s5p_dsim_enable_hs_clock(dsim->reg_base, 0);
- s5p_dsim_set_clock(dsim, dsim->dsim_info->e_byte_clk, 0);
-
-#if defined(CONFIG_CPU_EXYNOS4210)
- writel(0x1, dsim->reg_base + S5P_DSIM_SWRST);
-#endif
-
- if (dsim->pd->exit_d_phy)
- dsim->pd->exit_d_phy(dsim->reg_base);
-
- clk_disable(dsim->clock);
-
- if (dsim->pd->mipi_power)
- dsim->pd->mipi_power(0);
-
- dev_info(dsim->dev, "-%s\n", __func__);
-
- return;
-}
-
-void s5p_dsim_late_resume(void)
-{
- struct dsim_global *dsim = g_dsim;
-
- dev_info(dsim->dev, "+%s\n", __func__);
-
- /* MIPI SIGNAL ON */
- if (dsim->pd->mipi_power)
- dsim->pd->mipi_power(1);
-
- clk_enable(dsim->clock);
- usleep_range(10000, 10000);
-
- if (dsim->mipi_ddi_pd->lcd_power_on)
- dsim->mipi_ddi_pd->lcd_power_on(dsim->dev, 1);
- usleep_range(25000, 25000);
-
- if (dsim->mipi_ddi_pd->lcd_reset)
- dsim->mipi_ddi_pd->lcd_reset();
- usleep_range(5000, 5000);
-
- s5p_dsim_late_resume_init_dsim(dsim);
- s5p_dsim_init_link(dsim);
- usleep_range(10000, 10000);
- s5p_dsim_set_hs_enable(dsim);
-#if defined(CONFIG_FB_S5P_S6E63M0)
- s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYCPU, 0);
-#else
- s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYCPU, 1);
-#endif
- s5p_dsim_set_display_mode(dsim, dsim->dsim_lcd_info, NULL);
- s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYLCDC, 1);
- /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 0); */
-
- dsim->mipi_ddi_pd->resume_complete = 1;
-
- dev_info(dsim->dev, "-%s\n", __func__);
-
- return;
-}
-
-#else
-#ifdef CONFIG_PM
-static int s5p_dsim_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct dsim_global *dsim = platform_get_drvdata(pdev);
-
- dev_info(&pdev->dev, "%s\n", __func__);
-
- dsim->mipi_ddi_pd->resume_complete = 0;
-
- if (dsim->mipi_drv->suspend)
- dsim->mipi_drv->suspend(&pdev->dev, state);
- else
- dev_warn(&pdev->dev, "suspend func is null\n");
-
- clk_disable(dsim->clock);
-
- if (dsim->pd->mipi_power)
- dsim->pd->mipi_power(0);
- else
- dev_warn(&pdev->dev, "mipi_power func is null\n");
-
- return 0;
-}
-
-static int s5p_dsim_resume(struct platform_device *pdev)
-{
- u32 int_stat;
-
- struct dsim_global *dsim = platform_get_drvdata(pdev);
-
- dev_info(&pdev->dev, "%s\n", __func__);
-
- if (dsim->pd->mipi_power)
- dsim->pd->mipi_power(1);
- else
- dev_warn(&pdev->dev, "mipi_power func is null\n");
-
- usleep_range(10000, 10000);
-
- clk_enable(dsim->clock);
-
- if (dsim->mipi_drv->resume)
- dsim->mipi_drv->resume(&pdev->dev);
- else
- dev_warn(&pdev->dev, "resume func is null\n");
-
- s5p_dsim_init_dsim(dsim);
- s5p_dsim_init_link(dsim);
-
- s5p_dsim_set_hs_enable(dsim);
- s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYCPU, 1);
-
- msleep(120);
-
- /* initialize lcd panel */
- if (dsim->mipi_drv->init)
- dsim->mipi_drv->init(&pdev->dev);
- else
- dev_warn(&pdev->dev, "init func is null\n");
-
- s5p_dsim_set_display_mode(dsim, dsim->dsim_lcd_info, NULL);
-
- s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYLCDC, 1);
-
- int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK);
-
- int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) |
- (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) |
- (0x01<<S5P_DSIM_INT_RX_TE) | (0x01<<S5P_DSIM_INT_RX_ACK) |
- (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) |
- (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY));
-
- writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK);
-
- dsim->mipi_ddi_pd->resume_complete = 1;
-
- return 0;
-}
-#else
-#define s5p_dsim_suspend NULL
-#define s5p_dsim_resume NULL
-#endif
-#endif
-
-u32 read_dsim_register(u32 num)
-{
- struct dsim_global *dsim = g_dsim;
-
- return readl(dsim->reg_base + (num*4));
-}
-
-static ssize_t hs_toggle_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- char temp[3];
- struct dsim_global *dsim = container_of(dev, struct dsim_global, panel);
-
- sprintf(temp, "%d\n", jiffies_to_msecs(dsim->dsim_info->hs_toggle));
- strcpy(buf, temp);
-
- return strlen(buf);
-}
-
-static int hs_toggle_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- int value;
- int rc;
- struct dsim_global *dsim = container_of(dev, struct dsim_global, panel);
-
- rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value);
- if (rc < 0)
- return rc;
- else {
- dev_info(dev, "%s - %d, %d\n", __func__, jiffies_to_msecs(dsim->dsim_info->hs_toggle), value);
-
- if (value == 1) {
- dsim->dsim_info->hs_toggle = msecs_to_jiffies(3000);
- s5p_dsim_frame_done_interrupt_enable(dsim, 1);
- schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(120000));
- } else {
- dsim->dsim_info->hs_toggle = 0;
- s5p_dsim_frame_done_interrupt_enable(dsim, 0);
- cancel_delayed_work(&dsim->check_hs_toggle_work);
- }
- }
- return size;
-}
-
-static DEVICE_ATTR(hs_toggle, 0644, hs_toggle_show, hs_toggle_store);
-
-static ssize_t dsim_dump_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int reg_val, i;
- char temp[50];
- struct dsim_global *dsim = dev_get_drvdata(dev);
-
- for (i = 0; i < 25; i++) {
- reg_val = readl(dsim->reg_base + i*4);
- sprintf(temp, "[DSIM]0x11C8_00%02X = 0x%08X\n", (i*4), reg_val);
- strcat(buf, temp);
- }
-
- return strlen(buf);
-}
-static DEVICE_ATTR(dsim_dump, 0444, dsim_dump_show, NULL);
-
-static struct dsim_ops s5p_dsim_ops = {
- .cmd_write = s5p_dsim_wr_data,
- .cmd_read = s5p_dsim_rd_data,
- .suspend = s5p_dsim_early_suspend,
- .resume = s5p_dsim_late_resume,
-};
-
-static int s5p_dsim_probe(struct platform_device *pdev)
-{
- struct resource *res;
- int ret = -1;
- u32 int_stat;
- struct dsim_global *dsim;
-
- dsim = kzalloc(sizeof(struct dsim_global), GFP_KERNEL);
- if (!dsim) {
- pr_err("failed to allocate for dsim_global\n");
- ret = -ENOMEM;
- goto err_alloc;
- }
-
- g_dsim = dsim;
-
- dsim->pd = to_dsim_plat(&pdev->dev);
- if (!dsim->pd) {
- dev_err(&pdev->dev, "platform data is NULL\n");
- return -EINVAL;
- }
-
- dsim->dev = &pdev->dev;
-
- /* set dsim config data, dsim lcd config data and lcd panel data. */
- dsim->dsim_info = dsim->pd->dsim_info;
- dsim->dsim_lcd_info = dsim->pd->dsim_lcd_info;
- dsim->lcd_panel_info = (struct s3cfb_lcd *) dsim->dsim_lcd_info->lcd_panel_info;
- dsim->mipi_ddi_pd = (struct mipi_ddi_platform_data *) dsim->dsim_lcd_info->mipi_ddi_pd;
- dsim->mipi_ddi_pd->te_irq = dsim->pd->te_irq;
-
- if (dsim->pd->mipi_power)
- dsim->pd->mipi_power(1);
-
- strcpy(dsim->pd->lcd_panel_name, dsim->lcd_panel_info->name);
-
- /* clock */
- dsim->clock = clk_get(&pdev->dev, dsim->pd->clk_name);
- if (IS_ERR(dsim->clock)) {
- dev_err(&pdev->dev, "failed to get dsim clock source\n");
- return -EINVAL;
- }
-
- clk_enable(dsim->clock);
-
- /* io memory */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "failed to get io memory region\n");
- ret = -EINVAL;
- goto err_clk_disable;
- }
-
- /* request mem region */
- res = request_mem_region(res->start,
- res->end - res->start + 1, pdev->name);
- if (!res) {
- dev_err(&pdev->dev, "failed to request io memory region\n");
- ret = -EINVAL;
- goto err_clk_disable;
- }
-
- /* ioremap for register block */
- dsim->reg_base = (unsigned int)ioremap(res->start,
- res->end - res->start + 1);
- if (!dsim->reg_base) {
- dev_err(&pdev->dev, "failed to remap io region\n");
- ret = -EINVAL;
- goto err_clk_disable;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(&pdev->dev, "failed to request dsim irq resource\n");
- ret = -EINVAL;
- goto err_clk_disable;
- }
- /* dsim->irq = res->start; */
-
- /* clear interrupt */
- /* int_stat = readl(dsim->reg_base + S5P_DSIM_INTSRC); */
- int_stat = 0xffffffff;
- writel(int_stat, dsim->reg_base + S5P_DSIM_INTSRC);
-
- /* enable interrupts */
- int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK);
-
- int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) |
- (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) |
- (0x01<<S5P_DSIM_INT_RX_TE) | (0x01<<S5P_DSIM_INT_RX_ACK) |
- (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) |
- (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY));
-
- writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK);
-
- init_completion(&dsim_rd_comp);
- init_completion(&dsim_wr_comp);
- mutex_init(&dsim_rd_wr_mutex);
-
- dsim->mipi_ddi_pd->resume_complete = 1;
- dsim->dsim_lcd_info->lcd_enabled = 1;
-
- ret = request_irq(res->start, (void *)s5p_dsim_isr, IRQF_DISABLED, pdev->name, dsim);
- if (ret != 0) {
- dev_err(&pdev->dev, "failed to request dsim irq\n");
- ret = -EINVAL;
- goto err_clk_disable;
- }
-
- INIT_DELAYED_WORK(&dsim->dsim_work, dsim_work_q_handler);
- INIT_DELAYED_WORK(&dsim->check_hs_toggle_work, dsim_check_hs_toggle_work_q_handler);
-
- dsim->ops = &s5p_dsim_ops;
-
- platform_set_drvdata(pdev, dsim);
-
- dsim->panel.parent = &pdev->dev;
- dev_set_name(&dsim->panel, dsim->pd->lcd_panel_name);
- ret = device_register(&dsim->panel);
- if (ret < 0) {
- dev_err(&pdev->dev, "faild device register\n");
- ret = -EINVAL;
- goto mipi_drv_err;
- }
-
- /* find lcd panel driver registered to mipi-dsi driver. */
- dsim->mipi_drv = scan_mipi_driver(dsim, dsim->pd->lcd_panel_name);
- if (dsim->mipi_drv == NULL) {
- dev_err(&pdev->dev, "mipi_drv is NULL\n");
- ret = -EINVAL;
- goto mipi_drv_err;
- }
-
- ret = dsim->mipi_drv->probe(&dsim->panel);
- if (ret < 0) {
- dev_err(&pdev->dev, "faild probe\n");
- ret = -EINVAL;
- goto mipi_drv_err;
- }
-
- dsim->state = DSIM_STATE_HSCLKEN;
-
- ret = device_create_file(&(pdev->dev), &dev_attr_dsim_dump);
- if (ret < 0)
- dev_err(&pdev->dev, "failed to add sysfs entries, %d\n", __LINE__);
-
- if (!dsim->dsim_info->hs_toggle) {
- ret = device_create_file(&dsim->panel, &dev_attr_hs_toggle);
- if (ret < 0)
- dev_err(&pdev->dev, "failed to add sysfs entries, %d\n", __LINE__);
- }
-
- if (dsim->dsim_info->hs_toggle)
- s5p_dsim_frame_done_interrupt_enable(dsim, 1);
-
- dev_info(&pdev->dev, "mipi-dsi driver has been probed\n");
-
-#if 0
-#ifdef CONFIG_HAS_WAKELOCK
-#ifdef CONFIG_HAS_EARLYSUSPEND
- dsim->early_suspend.suspend = s5p_dsim_early_suspend;
- dsim->early_suspend.resume = s5p_dsim_late_resume;
- dsim->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
- register_early_suspend(&dsim->early_suspend);
-#endif
-#endif
-#endif
- return 0;
-
-mipi_drv_err:
- free_irq(res->start, &dsim);
- dsim->pd->mipi_power(0);
-
-err_clk_disable:
- clk_disable(dsim->clock);
-err_alloc:
- return ret;
-}
-
-static int s5p_dsim_remove(struct platform_device *pdev)
-{
- return 0;
-}
-
-static struct platform_driver s5p_dsim_driver = {
- .probe = s5p_dsim_probe,
- .remove = s5p_dsim_remove,
-#ifndef CONFIG_HAS_EARLYSUSPEND
- .suspend = s5p_dsim_suspend,
- .resume = s5p_dsim_resume,
-#endif
- .driver = {
- .name = "s5p-dsim",
- .owner = THIS_MODULE,
- },
-};
-
-static int s5p_dsim_register(void)
-{
- return platform_driver_register(&s5p_dsim_driver);
-}
-
-static void s5p_dsim_unregister(void)
-{
- platform_driver_unregister(&s5p_dsim_driver);
-}
-
-module_init(s5p_dsim_register);
-module_exit(s5p_dsim_unregister);
-
-MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samusung MIPI-DSIM driver");
-MODULE_LICENSE("GPL");