123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896 |
- /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/module.h>
- #include <linux/interrupt.h>
- #include <linux/spinlock.h>
- #include <linux/delay.h>
- #include <linux/io.h>
- #include <linux/dma-mapping.h>
- #include <linux/slab.h>
- #include <linux/iopoll.h>
- #include <linux/interrupt.h>
- #include <linux/of_device.h>
- #include "dsi_v2.h"
- #include "dsi_io_v2.h"
- #include "dsi_host_v2.h"
- #include "mdss_debug.h"
- #include "mdp3.h"
- #define DSI_POLL_SLEEP_US 1000
- #define DSI_POLL_TIMEOUT_US 16000
- #define DSI_ESC_CLK_RATE 19200000
- #define DSI_DMA_CMD_TIMEOUT_MS 200
- #define VSYNC_PERIOD 17
- #define DSI_MAX_PKT_SIZE 10
- #define DSI_SHORT_PKT_DATA_SIZE 2
- #define DSI_MAX_BYTES_TO_READ 16
- struct dsi_host_v2_private {
- int irq_no;
- unsigned char *dsi_base;
- size_t dsi_reg_size;
- struct device dis_dev;
- int clk_count;
- int dsi_on;
- void (*debug_enable_clk)(int on);
- };
- static struct dsi_host_v2_private *dsi_host_private;
- static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable);
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- extern int dsi_ctrl_on;
- extern unsigned char *dsi_ctrl_base;
- extern void dumpreg(void);
- extern void mdp3_dump_clk(void);
- #endif
- int msm_dsi_init(void)
- {
- if (!dsi_host_private) {
- dsi_host_private = kzalloc(sizeof(struct dsi_host_v2_private),
- GFP_KERNEL);
- if (!dsi_host_private) {
- pr_err("fail to alloc dsi host private data\n");
- return -ENOMEM;
- }
- }
- return 0;
- }
- void msm_dsi_deinit(void)
- {
- kfree(dsi_host_private);
- dsi_host_private = NULL;
- }
- void msm_dsi_ack_err_status(unsigned char *ctrl_base)
- {
- u32 status;
- status = MIPI_INP(ctrl_base + DSI_ACK_ERR_STATUS);
- if (status) {
- MIPI_OUTP(ctrl_base + DSI_ACK_ERR_STATUS, status);
- /* Writing of an extra 0 needed to clear error bits */
- MIPI_OUTP(ctrl_base + DSI_ACK_ERR_STATUS, 0);
- pr_err("%s: status=%x\n", __func__, status);
- }
- }
- void msm_dsi_timeout_status(unsigned char *ctrl_base)
- {
- u32 status;
- status = MIPI_INP(ctrl_base + DSI_TIMEOUT_STATUS);
- if (status & 0x0111) {
- MIPI_OUTP(ctrl_base + DSI_TIMEOUT_STATUS, status);
- pr_err("%s: status=%x\n", __func__, status);
- }
- }
- void msm_dsi_dln0_phy_err(unsigned char *ctrl_base)
- {
- u32 status;
- status = MIPI_INP(ctrl_base + DSI_DLN0_PHY_ERR);
- if (status & 0x011111) {
- MIPI_OUTP(ctrl_base + DSI_DLN0_PHY_ERR, status);
- pr_err("%s: status=%x\n", __func__, status);
- }
- }
- void msm_dsi_fifo_status(unsigned char *ctrl_base)
- {
- u32 status;
- status = MIPI_INP(ctrl_base + DSI_FIFO_STATUS);
- if (status & 0x44444489) {
- MIPI_OUTP(ctrl_base + DSI_FIFO_STATUS, status);
- pr_err("%s: status=%x\n", __func__, status);
- }
- }
- void msm_dsi_status(unsigned char *ctrl_base)
- {
- u32 status;
- status = MIPI_INP(ctrl_base + DSI_STATUS);
- if (status & 0x80000000) {
- MIPI_OUTP(ctrl_base + DSI_STATUS, status);
- pr_err("%s: status=%x\n", __func__, status);
- }
- }
- void msm_dsi_error(unsigned char *ctrl_base)
- {
- msm_dsi_ack_err_status(ctrl_base);
- msm_dsi_timeout_status(ctrl_base);
- msm_dsi_fifo_status(ctrl_base);
- msm_dsi_status(ctrl_base);
- msm_dsi_dln0_phy_err(ctrl_base);
- }
- static void msm_dsi_set_irq_mask(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
- {
- u32 intr_ctrl;
- intr_ctrl = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
- intr_ctrl |= mask;
- MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, intr_ctrl);
- }
- static void msm_dsi_clear_irq_mask(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
- {
- u32 intr_ctrl;
- intr_ctrl = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
- intr_ctrl &= ~mask;
- MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, intr_ctrl);
- }
- static void msm_dsi_set_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
- {
- unsigned long flags;
- spin_lock_irqsave(&ctrl->irq_lock, flags);
- if (ctrl->dsi_irq_mask & mask) {
- spin_unlock_irqrestore(&ctrl->irq_lock, flags);
- return;
- }
- if (ctrl->dsi_irq_mask == 0) {
- enable_irq(dsi_host_private->irq_no);
- pr_debug("%s: IRQ Enable, mask=%x term=%x\n", __func__,
- (int)ctrl->dsi_irq_mask, (int)mask);
- }
- msm_dsi_set_irq_mask(ctrl, mask);
- ctrl->dsi_irq_mask |= mask;
- spin_unlock_irqrestore(&ctrl->irq_lock, flags);
- }
- static void msm_dsi_clear_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
- {
- unsigned long flags;
- spin_lock_irqsave(&ctrl->irq_lock, flags);
- if (!(ctrl->dsi_irq_mask & mask)) {
- spin_unlock_irqrestore(&ctrl->irq_lock, flags);
- return;
- }
- ctrl->dsi_irq_mask &= ~mask;
- if (ctrl->dsi_irq_mask == 0) {
- disable_irq(dsi_host_private->irq_no);
- pr_debug("%s: IRQ Disable, mask=%x term=%x\n", __func__,
- (int)ctrl->dsi_irq_mask, (int)mask);
- }
- msm_dsi_clear_irq_mask(ctrl, mask);
- spin_unlock_irqrestore(&ctrl->irq_lock, flags);
- }
- irqreturn_t msm_dsi_isr_handler(int irq, void *ptr)
- {
- u32 isr;
- struct mdss_dsi_ctrl_pdata *ctrl =
- (struct mdss_dsi_ctrl_pdata *)ptr;
- spin_lock(&ctrl->mdp_lock);
- if (ctrl->dsi_irq_mask == 0) {
- spin_unlock(&ctrl->mdp_lock);
- return IRQ_HANDLED;
- }
- isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
- MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
- pr_debug("%s: isr=%x", __func__, isr);
- if (isr & DSI_INTR_ERROR) {
- pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
- msm_dsi_error(dsi_host_private->dsi_base);
- }
- if (isr & DSI_INTR_VIDEO_DONE)
- complete(&ctrl->video_comp);
- if (isr & DSI_INTR_CMD_DMA_DONE)
- complete(&ctrl->dma_comp);
- if (isr & DSI_INTR_BTA_DONE)
- complete(&ctrl->bta_comp);
- if (isr & DSI_INTR_CMD_MDP_DONE)
- complete(&ctrl->mdp_comp);
- spin_unlock(&ctrl->mdp_lock);
- return IRQ_HANDLED;
- }
- int msm_dsi_irq_init(struct device *dev, int irq_no,
- struct mdss_dsi_ctrl_pdata *ctrl)
- {
- int ret;
- u32 isr;
- msm_dsi_ahb_ctrl(1);
- isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
- isr &= ~DSI_INTR_ALL_MASK;
- MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
- msm_dsi_ahb_ctrl(0);
- ret = devm_request_irq(dev, irq_no, msm_dsi_isr_handler,
- IRQF_DISABLED, "DSI", ctrl);
- if (ret) {
- pr_err("msm_dsi_irq_init request_irq() failed!\n");
- return ret;
- }
- dsi_host_private->irq_no = irq_no;
- disable_irq(irq_no);
- return 0;
- }
- static void msm_dsi_get_cmd_engine(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- u32 dsi_ctrl;
- if (ctrl->panel_mode == DSI_VIDEO_MODE) {
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl | 0x04);
- }
- }
- static void msm_dsi_release_cmd_engine(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- u32 dsi_ctrl;
- if (ctrl->panel_mode == DSI_VIDEO_MODE) {
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- dsi_ctrl &= ~0x04;
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- }
- }
- static int msm_dsi_wait4mdp_done(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- int rc;
- unsigned long flag;
- spin_lock_irqsave(&ctrl->mdp_lock, flag);
- INIT_COMPLETION(ctrl->mdp_comp);
- msm_dsi_set_irq(ctrl, DSI_INTR_CMD_MDP_DONE_MASK);
- spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
- rc = wait_for_completion_timeout(&ctrl->mdp_comp,
- msecs_to_jiffies(VSYNC_PERIOD * 4));
- if (rc == 0) {
- pr_err("DSI wait 4 mdp done time out\n");
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- dumpreg();
- mdp3_dump_clk();
- panic("DSI wait 4 mdp done time out");
- #endif
- rc = -ETIME;
- } else if (!IS_ERR_VALUE(rc)) {
- rc = 0;
- }
- msm_dsi_clear_irq(ctrl, DSI_INTR_CMD_MDP_DONE_MASK);
- return rc;
- }
- void msm_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- int rc;
- u32 dsi_status;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- if (ctrl->panel_mode == DSI_VIDEO_MODE)
- return;
- dsi_status = MIPI_INP(ctrl_base + DSI_STATUS);
- if (dsi_status & 0x04) {
- pr_debug("dsi command engine is busy\n");
- rc = msm_dsi_wait4mdp_done(ctrl);
- if (rc)
- pr_err("Timed out waiting for mdp done");
- }
- }
- static int msm_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- int rc;
- unsigned long flag;
- spin_lock_irqsave(&ctrl->mdp_lock, flag);
- INIT_COMPLETION(ctrl->video_comp);
- msm_dsi_set_irq(ctrl, DSI_INTR_VIDEO_DONE_MASK);
- spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
- rc = wait_for_completion_timeout(&ctrl->video_comp,
- msecs_to_jiffies(VSYNC_PERIOD * 4));
- if (rc == 0) {
- pr_err("DSI wait 4 video done time out\n");
- rc = -ETIME;
- } else if (!IS_ERR_VALUE(rc)) {
- rc = 0;
- }
- msm_dsi_clear_irq(ctrl, DSI_INTR_VIDEO_DONE_MASK);
- return rc;
- }
- static int msm_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- int rc = 0;
- u32 dsi_status;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- if (ctrl->panel_mode == DSI_CMD_MODE)
- return rc;
- dsi_status = MIPI_INP(ctrl_base + DSI_STATUS);
- if (dsi_status & 0x08) {
- pr_debug("dsi command in video mode wait for active region\n");
- rc = msm_dsi_wait4video_done(ctrl);
- /* delay 4-5 ms to skip BLLP */
- if (!rc)
- usleep_range(4000, 5000);
- }
- return rc;
- }
- void msm_dsi_host_init(struct mipi_panel_info *pinfo)
- {
- u32 dsi_ctrl, data;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- pr_debug("msm_dsi_host_init\n");
- pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
- if (pinfo->mode == DSI_VIDEO_MODE) {
- data = 0;
- if (pinfo->pulse_mode_hsa_he)
- data |= BIT(28);
- if (pinfo->hfp_power_stop)
- data |= BIT(24);
- if (pinfo->hbp_power_stop)
- data |= BIT(20);
- if (pinfo->hsa_power_stop)
- data |= BIT(16);
- if (pinfo->eof_bllp_power_stop)
- data |= BIT(15);
- if (pinfo->bllp_power_stop)
- data |= BIT(12);
- data |= ((pinfo->traffic_mode & 0x03) << 8);
- data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */
- data |= (pinfo->vc & 0x03);
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_CTRL, data);
- data = 0;
- data |= ((pinfo->rgb_swap & 0x07) << 12);
- if (pinfo->b_sel)
- data |= BIT(8);
- if (pinfo->g_sel)
- data |= BIT(4);
- if (pinfo->r_sel)
- data |= BIT(0);
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_DATA_CTRL, data);
- } else if (pinfo->mode == DSI_CMD_MODE) {
- data = 0;
- data |= ((pinfo->interleave_max & 0x0f) << 20);
- data |= ((pinfo->rgb_swap & 0x07) << 16);
- if (pinfo->b_sel)
- data |= BIT(12);
- if (pinfo->g_sel)
- data |= BIT(8);
- if (pinfo->r_sel)
- data |= BIT(4);
- data |= (pinfo->dst_format & 0x0f); /* 4 bits */
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_CTRL, data);
- /* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
- data = pinfo->wr_mem_continue & 0x0ff;
- data <<= 8;
- data |= (pinfo->wr_mem_start & 0x0ff);
- if (pinfo->insert_dcs_cmd)
- data |= BIT(16);
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL,
- data);
- } else
- pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
- dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */
- if (pinfo->crc_check)
- dsi_ctrl |= BIT(24);
- if (pinfo->ecc_check)
- dsi_ctrl |= BIT(20);
- if (pinfo->data_lane3)
- dsi_ctrl |= BIT(7);
- if (pinfo->data_lane2)
- dsi_ctrl |= BIT(6);
- if (pinfo->data_lane1)
- dsi_ctrl |= BIT(5);
- if (pinfo->data_lane0)
- dsi_ctrl |= BIT(4);
- /* from frame buffer, low power mode */
- /* DSI_COMMAND_MODE_DMA_CTRL */
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, 0x14000000);
- data = 0;
- if (pinfo->te_sel)
- data |= BIT(31);
- data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */
- data |= pinfo->dma_trigger; /* cmd dma trigger */
- data |= (pinfo->stream & 0x01) << 8;
- MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, data);
- /* DSI_LAN_SWAP_CTRL */
- MIPI_OUTP(ctrl_base + DSI_LANE_SWAP_CTRL, pinfo->dlane_swap);
- /* clock out ctrl */
- data = pinfo->t_clk_post & 0x3f; /* 6 bits */
- data <<= 8;
- data |= pinfo->t_clk_pre & 0x3f; /* 6 bits */
- /* DSI_CLKOUT_TIMING_CTRL */
- MIPI_OUTP(ctrl_base + DSI_CLKOUT_TIMING_CTRL, data);
- data = 0;
- if (pinfo->rx_eot_ignore)
- data |= BIT(4);
- if (pinfo->tx_eot_append)
- data |= BIT(0);
- MIPI_OUTP(ctrl_base + DSI_EOT_PACKET_CTRL, data);
- /* allow only ack-err-status to generate interrupt */
- /* DSI_ERR_INT_MASK0 */
- MIPI_OUTP(ctrl_base + DSI_ERR_INT_MASK0, 0x13ff3fe0);
- /* turn esc, byte, dsi, pclk, sclk, hclk on */
- MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
- dsi_ctrl |= BIT(0); /* enable dsi */
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- wmb();
- }
- void dsi_set_tx_power_mode(int mode)
- {
- u32 data;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- data = MIPI_INP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL);
- if (mode == 0)
- data &= ~BIT(26);
- else
- data |= BIT(26);
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
- }
- void msm_dsi_sw_reset(void)
- {
- u32 dsi_ctrl;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- pr_debug("msm_dsi_sw_reset\n");
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- dsi_ctrl &= ~0x01;
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- wmb();
- /* turn esc, byte, dsi, pclk, sclk, hclk on */
- MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
- wmb();
- MIPI_OUTP(ctrl_base + DSI_SOFT_RESET, 0x01);
- wmb();
- MIPI_OUTP(ctrl_base + DSI_SOFT_RESET, 0x00);
- wmb();
- }
- void msm_dsi_controller_cfg(int enable)
- {
- u32 dsi_ctrl, status;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- pr_debug("msm_dsi_controller_cfg\n");
- /* Check for CMD_MODE_DMA_BUSY */
- if (readl_poll_timeout((ctrl_base + DSI_STATUS),
- status,
- ((status & 0x02) == 0),
- DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US)) {
- pr_err("%s: DSI status=%x failed\n", __func__, status);
- pr_err("%s: Doing sw reset\n", __func__);
- msm_dsi_sw_reset();
- }
- /* Check for x_HS_FIFO_EMPTY */
- if (readl_poll_timeout((ctrl_base + DSI_FIFO_STATUS),
- status,
- ((status & 0x11111000) == 0x11111000),
- DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US))
- pr_err("%s: FIFO status=%x failed\n", __func__, status);
- /* Check for VIDEO_MODE_ENGINE_BUSY */
- if (readl_poll_timeout((ctrl_base + DSI_STATUS),
- status,
- ((status & 0x08) == 0),
- DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US)) {
- pr_err("%s: DSI status=%x\n", __func__, status);
- pr_err("%s: Doing sw reset\n", __func__);
- msm_dsi_sw_reset();
- }
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- if (enable)
- dsi_ctrl |= 0x01;
- else
- dsi_ctrl &= ~0x01;
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- wmb();
- }
- void msm_dsi_op_mode_config(int mode, struct mdss_panel_data *pdata)
- {
- u32 dsi_ctrl;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- pr_debug("msm_dsi_op_mode_config\n");
- dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
- if (dsi_ctrl & DSI_VIDEO_MODE_EN)
- dsi_ctrl &= ~(DSI_CMD_MODE_EN|DSI_EN);
- else
- dsi_ctrl &= ~(DSI_CMD_MODE_EN|DSI_VIDEO_MODE_EN|DSI_EN);
- if (mode == DSI_VIDEO_MODE) {
- dsi_ctrl |= (DSI_VIDEO_MODE_EN|DSI_EN);
- } else { /* command mode */
- dsi_ctrl |= (DSI_CMD_MODE_EN|DSI_EN);
- /*For Video mode panel, keep Video and Cmd mode ON */
- if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
- dsi_ctrl |= DSI_VIDEO_MODE_EN;
- }
- pr_debug("%s: dsi_ctrl=%x\n", __func__, dsi_ctrl);
- MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- wmb();
- }
- int msm_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsi_buf *tp)
- {
- int len, rc;
- unsigned long size, addr;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- unsigned long flag;
- #if defined(CONFIG_DSI_HOST_DEBUG)
- int i = 0;
- char *bp;
- bp = tp->data;
- printk("%s: ", __func__);
- for (i = 0; i < tp->len; i++)
- printk("%02X ", *bp++);
- printk("\n");
- #endif
- len = ALIGN(tp->len, 4);
- size = ALIGN(tp->len, SZ_4K);
- tp->dmap = dma_map_single(&dsi_host_private->dis_dev, tp->data, size,
- DMA_TO_DEVICE);
- if (dma_mapping_error(&dsi_host_private->dis_dev, tp->dmap)) {
- pr_err("%s: dmap mapp failed\n", __func__);
- return -ENOMEM;
- }
- addr = tp->dmap;
- msm_dsi_get_cmd_engine(ctrl);
- spin_lock_irqsave(&ctrl->mdp_lock, flag);
- INIT_COMPLETION(ctrl->dma_comp);
- msm_dsi_set_irq(ctrl, DSI_INTR_CMD_DMA_DONE_MASK);
- spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
- MIPI_OUTP(ctrl_base + DSI_DMA_CMD_OFFSET, addr);
- MIPI_OUTP(ctrl_base + DSI_DMA_CMD_LENGTH, len);
- wmb();
- MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
- wmb();
- rc = wait_for_completion_timeout(&ctrl->dma_comp,
- msecs_to_jiffies(DSI_DMA_CMD_TIMEOUT_MS));
- if (rc == 0) {
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- dumpreg();
- mdp3_dump_clk();
- #endif
- pr_err("DSI command transaction time out\n");
- rc = -ETIME;
- } else if (!IS_ERR_VALUE(rc)) {
- rc = 0;
- }
- dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
- DMA_TO_DEVICE);
- tp->dmap = 0;
- msm_dsi_clear_irq(ctrl, DSI_INTR_CMD_DMA_DONE_MASK);
- msm_dsi_release_cmd_engine(ctrl);
- return rc;
- }
- /* MIPI_DSI_MRPS, Maximum Return Packet Size */
- static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
- static struct dsi_cmd_desc pkt_size_cmd = {
- {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
- max_pktsize,
- };
- int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsi_buf *rp, int rlen)
- {
- u32 *lp, data, *temp;
- int i, j = 0, off, cnt;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- char reg[16];
- int repeated_bytes = 0;
- lp = (u32 *)rp->data;
- temp = (u32 *)reg;
- cnt = rlen;
- cnt += 3;
- cnt >>= 2;
- if (cnt > 4)
- cnt = 4; /* 4 x 32 bits registers only */
- if (rlen == 4)
- rp->read_cnt = 4;
- else
- rp->read_cnt = (max_pktsize[0] + 6);
- if (rp->read_cnt > 16) {
- int bytes_shifted, data_lost = 0, rem_header_bytes = 0;
- /* Any data more than 16 bytes will be shifted out */
- bytes_shifted = rp->read_cnt - rlen;
- if (bytes_shifted >= 4)
- data_lost = bytes_shifted - 4; /* remove dcs header */
- else
- rem_header_bytes = 4 - bytes_shifted; /* rem header */
- /*
- * (rp->len - 4) -> current rx buffer data length.
- * If data_lost > 0, then ((rp->len - 4) - data_lost) will be
- * the number of repeating bytes.
- * If data_lost == 0, then ((rp->len - 4) + rem_header_bytes)
- * will be the number of bytes repeating in between rx buffer
- * and the current RDBK_DATA registers. We need to skip the
- * repeating bytes.
- */
- repeated_bytes = (rp->len - 4) - data_lost + rem_header_bytes;
- }
- off = DSI_RDBK_DATA0;
- off += ((cnt - 1) * 4);
- for (i = 0; i < cnt; i++) {
- data = (u32)MIPI_INP(ctrl_base + off);
- /* to network byte order */
- if (!repeated_bytes)
- *lp++ = ntohl(data);
- else
- *temp++ = ntohl(data);
- pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
- __func__, data, ntohl(data));
- off -= 4;
- if (rlen == 4)
- rp->len += sizeof(*lp);
- }
- /* Skip duplicates and append other data to the rx buffer */
- if (repeated_bytes) {
- for (i = repeated_bytes; i < 16; i++)
- rp->data[j++] = reg[i];
- }
- return rlen;
- }
- static int msm_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsi_cmd_desc *cmds, int cnt)
- {
- struct dsi_buf *tp;
- struct dsi_cmd_desc *cm;
- struct dsi_ctrl_hdr *dchdr;
- int len;
- int rc = 0;
- tp = &ctrl->tx_buf;
- mdss_dsi_buf_init(tp);
- cm = cmds;
- len = 0;
- while (cnt--) {
- dchdr = &cm->dchdr;
- mdss_dsi_buf_reserve(tp, len);
- len = mdss_dsi_cmd_dma_add(tp, cm);
- if (!len) {
- pr_err("%s: failed to add cmd = 0x%x\n",
- __func__, cm->payload[0]);
- rc = -EINVAL;
- goto dsi_cmds_tx_err;
- }
- if (dchdr->last) {
- tp->data = tp->start; /* begin of buf */
- rc = msm_dsi_wait4video_eng_busy(ctrl);
- if (rc) {
- pr_err("%s: wait4video_eng failed\n", __func__);
- goto dsi_cmds_tx_err;
- }
- rc = msm_dsi_cmd_dma_tx(ctrl, tp);
- if (IS_ERR_VALUE(len)) {
- pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n",
- __func__, cmds->payload[0]);
- goto dsi_cmds_tx_err;
- }
- if (dchdr->wait)
- usleep(dchdr->wait * 1000);
- mdss_dsi_buf_init(tp);
- len = 0;
- }
- cm++;
- }
- dsi_cmds_tx_err:
- return rc;
- }
- static int msm_dsi_parse_rx_response(struct dsi_buf *rp)
- {
- int rc = 0;
- unsigned char cmd;
- cmd = rp->data[0];
- switch (cmd) {
- case DTYPE_ACK_ERR_RESP:
- pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
- rc = -EINVAL;
- break;
- case DTYPE_GEN_READ1_RESP:
- case DTYPE_DCS_READ1_RESP:
- mdss_dsi_short_read1_resp(rp);
- break;
- case DTYPE_GEN_READ2_RESP:
- case DTYPE_DCS_READ2_RESP:
- mdss_dsi_short_read2_resp(rp);
- break;
- case DTYPE_GEN_LREAD_RESP:
- case DTYPE_DCS_LREAD_RESP:
- mdss_dsi_long_read_resp(rp);
- break;
- default:
- rc = -EINVAL;
- pr_warn("%s: Unknown cmd received\n", __func__);
- break;
- }
- return rc;
- }
- static int msm_dsi_set_max_packet_size(struct mdss_dsi_ctrl_pdata *ctrl,
- int size)
- {
- struct dsi_buf *tp;
- int rc;
- tp = &ctrl->tx_buf;
- mdss_dsi_buf_init(tp);
- max_pktsize[0] = size;
- rc = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
- if (!rc) {
- pr_err("%s: failed to add max_pkt_size\n", __func__);
- return -EINVAL;
- }
- rc = msm_dsi_wait4video_eng_busy(ctrl);
- if (rc) {
- pr_err("%s: failed to wait4video_eng\n", __func__);
- return rc;
- }
- rc = msm_dsi_cmd_dma_tx(ctrl, tp);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: failed to tx max_pkt_size\n", __func__);
- return rc;
- }
- pr_debug("%s: max_pkt_size=%d sent\n", __func__, size);
- return rc;
- }
- /* read data length is less than or equal to 10 bytes*/
- static int msm_dsi_cmds_rx_1(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsi_cmd_desc *cmds, int rlen)
- {
- int rc;
- struct dsi_buf *tp, *rp;
- int rx_byte = 0;
- if (rlen <= 2)
- rx_byte = 4;
- else
- rx_byte = DSI_MAX_BYTES_TO_READ;
- tp = &ctrl->tx_buf;
- rp = &ctrl->rx_buf;
- mdss_dsi_buf_init(rp);
- rc = msm_dsi_set_max_packet_size(ctrl, rlen);
- if (rc) {
- pr_err("%s: dsi_set_max_pkt failed\n", __func__);
- rc = -EINVAL;
- goto dsi_cmds_rx_1_error;
- }
- mdss_dsi_buf_init(tp);
- rc = mdss_dsi_cmd_dma_add(tp, cmds);
- if (!rc) {
- pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
- rc = -EINVAL;
- goto dsi_cmds_rx_1_error;
- }
- rc = msm_dsi_wait4video_eng_busy(ctrl);
- if (rc) {
- pr_err("%s: wait4video_eng failed\n", __func__);
- goto dsi_cmds_rx_1_error;
- }
- rc = msm_dsi_cmd_dma_tx(ctrl, tp);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: msm_dsi_cmd_dma_tx failed\n", __func__);
- goto dsi_cmds_rx_1_error;
- }
- if (rlen <= DSI_SHORT_PKT_DATA_SIZE) {
- msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
- } else {
- msm_dsi_cmd_dma_rx(ctrl, rp, rx_byte);
- rp->len = rx_byte - 2; /*2 bytes for CRC*/
- rp->len = rp->len - (DSI_MAX_PKT_SIZE - rlen);
- rp->data = rp->start + (16 - (rlen + 2 + DSI_HOST_HDR_SIZE));
- }
- rc = msm_dsi_parse_rx_response(rp);
- dsi_cmds_rx_1_error:
- if (rc)
- rp->len = 0;
- return rc;
- }
- /* read data length is more than 10 bytes, which requires multiple DSI read*/
- static int msm_dsi_cmds_rx_2(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsi_cmd_desc *cmds, int rlen)
- {
- int rc;
- struct dsi_buf *tp, *rp;
- int pkt_size, data_bytes, dlen, end = 0, diff;
- tp = &ctrl->tx_buf;
- rp = &ctrl->rx_buf;
- mdss_dsi_buf_init(rp);
- pkt_size = DSI_MAX_PKT_SIZE;
- data_bytes = MDSS_DSI_LEN;
- while (!end) {
- rc = msm_dsi_set_max_packet_size(ctrl, pkt_size);
- if (rc)
- break;
- mdss_dsi_buf_init(tp);
- rc = mdss_dsi_cmd_dma_add(tp, cmds);
- if (!rc) {
- pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
- rc = -EINVAL;
- break;
- }
- rc = msm_dsi_wait4video_eng_busy(ctrl);
- if (rc) {
- pr_err("%s: wait4video_eng failed\n", __func__);
- break;
- }
- rc = msm_dsi_cmd_dma_tx(ctrl, tp);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: msm_dsi_cmd_dma_tx failed\n", __func__);
- break;
- }
- msm_dsi_cmd_dma_rx(ctrl, rp, DSI_MAX_BYTES_TO_READ);
- if (rlen <= data_bytes) {
- diff = data_bytes - rlen;
- end = 1;
- } else {
- diff = 0;
- rlen -= data_bytes;
- }
- dlen = DSI_MAX_BYTES_TO_READ - 2;
- dlen -= diff;
- rp->data += dlen;
- rp->len += dlen;
- if (!end) {
- data_bytes = 14;
- if (rlen < data_bytes)
- pkt_size += rlen;
- else
- pkt_size += data_bytes;
- }
- pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
- __func__, (int) (unsigned long) rp->data,
- rp->len, dlen, diff);
- }
- if (!rc) {
- rp->data = rp->start;
- rc = msm_dsi_parse_rx_response(rp);
- }
- if (rc)
- rp->len = 0;
- return rc;
- }
- int msm_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dsi_cmd_desc *cmds, int rlen)
- {
- int rc;
- if (rlen <= DSI_MAX_PKT_SIZE)
- rc = msm_dsi_cmds_rx_1(ctrl, cmds, rlen);
- else
- rc = msm_dsi_cmds_rx_2(ctrl, cmds, rlen);
- return rc;
- }
- void msm_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dcs_cmd_req *req)
- {
- int ret;
- ret = msm_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt);
- if (req->cb)
- req->cb(ret);
- }
- void msm_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
- struct dcs_cmd_req *req)
- {
- struct dsi_buf *rp;
- int len = 0;
- if (req->rbuf) {
- rp = &ctrl->rx_buf;
- len = msm_dsi_cmds_rx(ctrl, req->cmds, req->rlen);
- memcpy(req->rbuf, rp->data, rp->len);
- } else {
- pr_err("%s: No rx buffer provided\n", __func__);
- }
- if (req->cb)
- req->cb(len);
- }
- int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
- {
- struct dcs_cmd_req *req;
- int dsi_on;
- int ret = -EINVAL;
- mutex_lock(&ctrl->mutex);
- dsi_on = dsi_host_private->dsi_on;
- mutex_unlock(&ctrl->mutex);
- if (!dsi_on) {
- pr_err("try to send DSI commands while dsi is off\n");
- return ret;
- }
- mutex_lock(&ctrl->cmd_mutex);
- req = mdss_dsi_cmdlist_get(ctrl);
- if (!req) {
- mutex_unlock(&ctrl->cmd_mutex);
- return ret;
- }
- /*
- * mdss interrupt is generated in mdp core clock domain
- * mdp clock need to be enabled to receive dsi interrupt
- * also, axi bus bandwidth need since dsi controller will
- * fetch dcs commands from axi bus
- */
- mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P);
- msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
- if (0 == (req->flags & CMD_REQ_LP_MODE))
- dsi_set_tx_power_mode(0);
- if (req->flags & CMD_REQ_RX)
- msm_dsi_cmdlist_rx(ctrl, req);
- else
- msm_dsi_cmdlist_tx(ctrl, req);
- if (0 == (req->flags & CMD_REQ_LP_MODE))
- dsi_set_tx_power_mode(1);
- msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
- mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P);
- mutex_unlock(&ctrl->cmd_mutex);
- return 0;
- }
- static int msm_dsi_cal_clk_rate(struct mdss_panel_data *pdata,
- u32 *bitclk_rate,
- u32 *dsiclk_rate,
- u32 *byteclk_rate,
- u32 *pclk_rate)
- {
- struct mdss_panel_info *pinfo;
- struct mipi_panel_info *mipi;
- u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
- int lanes;
- pinfo = &pdata->panel_info;
- mipi = &pdata->panel_info.mipi;
- hbp = pdata->panel_info.lcdc.h_back_porch;
- hfp = pdata->panel_info.lcdc.h_front_porch;
- vbp = pdata->panel_info.lcdc.v_back_porch;
- vfp = pdata->panel_info.lcdc.v_front_porch;
- hspw = pdata->panel_info.lcdc.h_pulse_width;
- vspw = pdata->panel_info.lcdc.v_pulse_width;
- width = pdata->panel_info.xres;
- height = pdata->panel_info.yres;
- lanes = 0;
- if (mipi->data_lane0)
- lanes++;
- if (mipi->data_lane1)
- lanes++;
- if (mipi->data_lane2)
- lanes++;
- if (mipi->data_lane3)
- lanes++;
- if (lanes == 0)
- return -EINVAL;
- *bitclk_rate = (width + hbp + hfp + hspw) * (height + vbp + vfp + vspw);
- *bitclk_rate *= mipi->frame_rate;
- *bitclk_rate *= pdata->panel_info.bpp;
- *bitclk_rate /= lanes;
- *byteclk_rate = *bitclk_rate / 8;
- *dsiclk_rate = *byteclk_rate * lanes;
- *pclk_rate = *byteclk_rate * lanes * 8 / pdata->panel_info.bpp;
- pr_debug("dsiclk_rate=%u, byteclk=%u, pck_=%u\n",
- *dsiclk_rate, *byteclk_rate, *pclk_rate);
- return 0;
- }
- static int msm_dsi_on(struct mdss_panel_data *pdata)
- {
- int ret = 0;
- u32 clk_rate;
- struct mdss_panel_info *pinfo;
- struct mipi_panel_info *mipi;
- u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
- u32 ystride, bpp, data;
- u32 dummy_xres, dummy_yres;
- u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
- unsigned char *ctrl_base = dsi_host_private->dsi_base;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- pr_debug("msm_dsi_on\n");
- pinfo = &pdata->panel_info;
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- mutex_lock(&ctrl_pdata->mutex);
- if (!pdata->panel_info.dynamic_switch_pending) {
- ret = msm_dss_enable_vreg(
- ctrl_pdata->power_data.vreg_config,
- ctrl_pdata->power_data.num_vreg, 1);
- if (ret) {
- pr_err("%s: DSI power on failed\n", __func__);
- mutex_unlock(&ctrl_pdata->mutex);
- return ret;
- }
- }
- msm_dsi_ahb_ctrl(1);
- msm_dsi_phy_sw_reset(dsi_host_private->dsi_base);
- msm_dsi_phy_init(dsi_host_private->dsi_base, pdata);
- msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
- &byteclk_rate, &pclk_rate);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
- byteclk_rate, pclk_rate);
- msm_dsi_prepare_clocks();
- msm_dsi_clk_enable();
- clk_rate = pdata->panel_info.clk_rate;
- clk_rate = min(clk_rate, pdata->panel_info.clk_max);
- hbp = pdata->panel_info.lcdc.h_back_porch;
- hfp = pdata->panel_info.lcdc.h_front_porch;
- vbp = pdata->panel_info.lcdc.v_back_porch;
- vfp = pdata->panel_info.lcdc.v_front_porch;
- hspw = pdata->panel_info.lcdc.h_pulse_width;
- vspw = pdata->panel_info.lcdc.v_pulse_width;
- width = pdata->panel_info.xres;
- height = pdata->panel_info.yres;
- mipi = &pdata->panel_info.mipi;
- if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
- dummy_xres = pdata->panel_info.lcdc.xres_pad;
- dummy_yres = pdata->panel_info.lcdc.yres_pad;
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_ACTIVE_H,
- ((hspw + hbp + width + dummy_xres) << 16 |
- (hspw + hbp)));
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_ACTIVE_V,
- ((vspw + vbp + height + dummy_yres) << 16 |
- (vspw + vbp)));
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_TOTAL,
- (vspw + vbp + height + dummy_yres +
- vfp - 1) << 16 | (hspw + hbp +
- width + dummy_xres + hfp - 1));
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_HSYNC, (hspw << 16));
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_VSYNC, 0);
- MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_VSYNC_VPOS,
- (vspw << 16));
- } else { /* command mode */
- if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
- bpp = 3;
- else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
- bpp = 3;
- else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
- bpp = 2;
- else
- bpp = 3; /* Default format set to RGB888 */
- ystride = width * bpp + 1;
- data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM0_CTRL,
- data);
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM1_CTRL,
- data);
- data = height << 16 | width;
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM1_TOTAL,
- data);
- MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM0_TOTAL,
- data);
- }
- msm_dsi_sw_reset();
- msm_dsi_host_init(mipi);
- if (mipi->force_clk_lane_hs) {
- u32 tmp;
- tmp = MIPI_INP(ctrl_base + DSI_LANE_CTRL);
- tmp |= (1<<28);
- MIPI_OUTP(ctrl_base + DSI_LANE_CTRL, tmp);
- wmb();
- }
- msm_dsi_op_mode_config(mipi->mode, pdata);
- msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
- dsi_host_private->clk_count = 1;
- dsi_host_private->dsi_on = 1;
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- dsi_ctrl_on = dsi_host_private->dsi_on;
- #endif
- mutex_unlock(&ctrl_pdata->mutex);
- return ret;
- }
- static int msm_dsi_off(struct mdss_panel_data *pdata)
- {
- int ret = 0;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- if (pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- ret = -EINVAL;
- return ret;
- }
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- pr_debug("msm_dsi_off\n");
- mutex_lock(&ctrl_pdata->mutex);
- msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
- msm_dsi_controller_cfg(0);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
- msm_dsi_clk_disable();
- msm_dsi_unprepare_clocks();
- msm_dsi_phy_off(dsi_host_private->dsi_base);
- msm_dsi_ahb_ctrl(0);
- if (!pdata->panel_info.dynamic_switch_pending) {
- ret = msm_dss_enable_vreg(
- ctrl_pdata->power_data.vreg_config,
- ctrl_pdata->power_data.num_vreg, 0);
- if (ret) {
- pr_err("%s: Panel power off failed\n", __func__);
- }
- }
- dsi_host_private->clk_count = 0;
- dsi_host_private->dsi_on = 0;
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- dsi_ctrl_on = dsi_host_private->dsi_on;
- #endif
- mutex_unlock(&ctrl_pdata->mutex);
- return ret;
- }
- static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
- {
- struct mdss_panel_info *pinfo;
- int ret = 0;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- if (pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- ret = -EINVAL;
- return ret;
- }
- pr_debug("%s:\n", __func__);
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- pinfo = &pdata->panel_info;
- mutex_lock(&ctrl_pdata->mutex);
- ret = msm_dss_enable_vreg(
- ctrl_pdata->power_data.vreg_config,
- ctrl_pdata->power_data.num_vreg, 1);
- if (ret) {
- pr_err("%s: DSI power on failed\n", __func__);
- mutex_unlock(&ctrl_pdata->mutex);
- return ret;
- }
- pinfo->panel_power_on = 1;
- ret = mdss_dsi_panel_reset(pdata, 1);
- if (ret) {
- pr_err("%s: Panel reset failed\n", __func__);
- mutex_unlock(&ctrl_pdata->mutex);
- return ret;
- }
- msm_dsi_ahb_ctrl(1);
- msm_dsi_prepare_clocks();
- msm_dsi_clk_enable();
- msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
- dsi_host_private->clk_count = 1;
- dsi_host_private->dsi_on = 1;
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- dsi_ctrl_on = dsi_host_private->dsi_on;
- #endif
- mutex_unlock(&ctrl_pdata->mutex);
- return 0;
- }
- static int msm_dsi_read_status(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- struct dcs_cmd_req cmdreq;
- memset(&cmdreq, 0, sizeof(cmdreq));
- cmdreq.cmds = ctrl->status_cmds.cmds;
- cmdreq.cmds_cnt = ctrl->status_cmds.cmd_cnt;
- cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL | CMD_REQ_RX;
- cmdreq.rlen = 1;
- cmdreq.cb = NULL;
- cmdreq.rbuf = ctrl->status_buf.data;
- return mdss_dsi_cmdlist_put(ctrl, &cmdreq);
- }
- /**
- * msm_dsi_reg_status_check() - Check dsi panel status through reg read
- * @ctrl_pdata: pointer to the dsi controller structure
- *
- * This function can be used to check the panel status through reading the
- * status register from the panel.
- *
- * Return: positive value if the panel is in good state, negative value or
- * zero otherwise.
- */
- int msm_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
- {
- int ret = 0;
- if (ctrl_pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- return 0;
- }
- pr_debug("%s: Checking Register status\n", __func__);
- msm_dsi_clk_ctrl(&ctrl_pdata->panel_data, 1);
- if (ctrl_pdata->status_cmds.link_state == DSI_HS_MODE)
- dsi_set_tx_power_mode(0);
- ret = msm_dsi_read_status(ctrl_pdata);
- if (ctrl_pdata->status_cmds.link_state == DSI_HS_MODE)
- dsi_set_tx_power_mode(1);
- if (ret == 0) {
- if (ctrl_pdata->status_buf.data[0] !=
- ctrl_pdata->status_value) {
- pr_err("%s: Read back value from panel is incorrect\n",
- __func__);
- ret = -EINVAL;
- } else {
- ret = 1;
- }
- } else {
- pr_err("%s: Read status register returned error\n", __func__);
- }
- msm_dsi_clk_ctrl(&ctrl_pdata->panel_data, 0);
- pr_debug("%s: Read register done with ret: %d\n", __func__, ret);
- return ret;
- }
- /**
- * msm_dsi_bta_status_check() - Check dsi panel status through bta check
- * @ctrl_pdata: pointer to the dsi controller structure
- *
- * This function can be used to check status of the panel using bta check
- * for the panel.
- *
- * Return: positive value if the panel is in good state, negative value or
- * zero otherwise.
- */
- static int msm_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
- {
- int ret = 0;
- if (ctrl_pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- return 0;
- }
- mutex_lock(&ctrl_pdata->cmd_mutex);
- msm_dsi_clk_ctrl(&ctrl_pdata->panel_data, 1);
- msm_dsi_cmd_mdp_busy(ctrl_pdata);
- msm_dsi_set_irq(ctrl_pdata, DSI_INTR_BTA_DONE_MASK);
- INIT_COMPLETION(ctrl_pdata->bta_comp);
- /* BTA trigger */
- MIPI_OUTP(dsi_host_private->dsi_base + DSI_CMD_MODE_BTA_SW_TRIGGER,
- 0x01);
- wmb();
- ret = wait_for_completion_killable_timeout(&ctrl_pdata->bta_comp,
- HZ/10);
- msm_dsi_clear_irq(ctrl_pdata, DSI_INTR_BTA_DONE_MASK);
- msm_dsi_clk_ctrl(&ctrl_pdata->panel_data, 0);
- mutex_unlock(&ctrl_pdata->cmd_mutex);
- if (ret <= 0)
- pr_err("%s: DSI BTA error: %i\n", __func__, __LINE__);
- pr_debug("%s: BTA done with ret: %d\n", __func__, ret);
- return ret;
- }
- static void msm_dsi_debug_enable_clock(int on)
- {
- if (dsi_host_private->debug_enable_clk)
- dsi_host_private->debug_enable_clk(on);
- if (on)
- msm_dsi_ahb_ctrl(1);
- else
- msm_dsi_ahb_ctrl(0);
- }
- static int msm_dsi_debug_init(void)
- {
- int rc;
- if (!mdss_res)
- return 0;
- dsi_host_private->debug_enable_clk =
- mdss_res->debug_inf.debug_enable_clock;
- mdss_res->debug_inf.debug_enable_clock = msm_dsi_debug_enable_clock;
- rc = mdss_debug_register_base("dsi0",
- dsi_host_private->dsi_base,
- dsi_host_private->dsi_reg_size);
- return rc;
- }
- static int dsi_get_panel_cfg(char *panel_cfg)
- {
- int rc;
- struct mdss_panel_cfg *pan_cfg = NULL;
- if (!panel_cfg)
- return MDSS_PANEL_INTF_INVALID;
- pan_cfg = mdp3_panel_intf_type(MDSS_PANEL_INTF_DSI);
- if (IS_ERR(pan_cfg)) {
- panel_cfg[0] = 0;
- return PTR_ERR(pan_cfg);
- } else if (!pan_cfg) {
- panel_cfg[0] = 0;
- return 0;
- }
- pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
- pan_cfg->arg_cfg);
- rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
- MDSS_MAX_PANEL_LEN);
- return rc;
- }
- static struct device_node *dsi_pref_prim_panel(
- struct platform_device *pdev)
- {
- struct device_node *dsi_pan_node = NULL;
- pr_debug("%s:%d: Select primary panel from dt\n",
- __func__, __LINE__);
- dsi_pan_node = of_parse_phandle(pdev->dev.of_node,
- "qcom,dsi-pref-prim-pan", 0);
- if (!dsi_pan_node)
- pr_err("%s:can't find panel phandle\n", __func__);
- return dsi_pan_node;
- }
- /**
- * dsi_find_panel_of_node(): find device node of dsi panel
- * @pdev: platform_device of the dsi ctrl node
- * @panel_cfg: string containing intf specific config data
- *
- * Function finds the panel device node using the interface
- * specific configuration data. This configuration data is
- * could be derived from the result of bootloader's GCDB
- * panel detection mechanism. If such config data doesn't
- * exist then this panel returns the default panel configured
- * in the device tree.
- *
- * returns pointer to panel node on success, NULL on error.
- */
- static struct device_node *dsi_find_panel_of_node(
- struct platform_device *pdev, char *panel_cfg)
- {
- int l;
- char *panel_name;
- struct device_node *dsi_pan_node = NULL, *mdss_node = NULL;
- if (!panel_cfg)
- return NULL;
- l = strlen(panel_cfg);
- if (!l) {
- /* no panel cfg chg, parse dt */
- pr_debug("%s:%d: no cmd line cfg present\n",
- __func__, __LINE__);
- dsi_pan_node = dsi_pref_prim_panel(pdev);
- } else {
- if (panel_cfg[0] != '0') {
- pr_err("%s:%d:ctrl id=[%d] not supported\n",
- __func__, __LINE__, panel_cfg[0]);
- return NULL;
- }
- /*
- * skip first two chars '<dsi_ctrl_id>' and
- * ':' to get to the panel name
- */
- panel_name = panel_cfg + 2;
- pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
- panel_cfg, panel_name);
- mdss_node = of_parse_phandle(pdev->dev.of_node,
- "qcom,mdss-mdp", 0);
- if (!mdss_node) {
- pr_err("%s: %d: mdss_node null\n",
- __func__, __LINE__);
- return NULL;
- }
- dsi_pan_node = of_find_node_by_name(mdss_node,
- panel_name);
- if (!dsi_pan_node) {
- pr_err("%s: invalid pan node\n",
- __func__);
- dsi_pan_node = dsi_pref_prim_panel(pdev);
- }
- }
- return dsi_pan_node;
- }
- static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
- {
- u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- pr_debug("%s:\n", __func__);
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
- mutex_lock(&ctrl_pdata->mutex);
- if (enable) {
- dsi_host_private->clk_count++;
- if (dsi_host_private->clk_count == 1) {
- msm_dsi_ahb_ctrl(1);
- msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
- &byteclk_rate, &pclk_rate);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
- byteclk_rate, pclk_rate);
- msm_dsi_prepare_clocks();
- msm_dsi_clk_enable();
- }
- } else {
- dsi_host_private->clk_count--;
- if (dsi_host_private->clk_count == 0) {
- msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
- msm_dsi_clk_disable();
- msm_dsi_unprepare_clocks();
- msm_dsi_ahb_ctrl(0);
- }
- }
- mutex_unlock(&ctrl_pdata->mutex);
- return 0;
- }
- void msm_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
- {
- init_completion(&ctrl->dma_comp);
- init_completion(&ctrl->mdp_comp);
- init_completion(&ctrl->bta_comp);
- init_completion(&ctrl->video_comp);
- spin_lock_init(&ctrl->irq_lock);
- spin_lock_init(&ctrl->mdp_lock);
- mutex_init(&ctrl->mutex);
- mutex_init(&ctrl->cmd_mutex);
- complete(&ctrl->mdp_comp);
- dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
- dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
- dsi_buf_alloc(&ctrl->status_buf, SZ_4K);
- ctrl->cmdlist_commit = msm_dsi_cmdlist_commit;
- ctrl->panel_mode = ctrl->panel_data.panel_info.mipi.mode;
- if (ctrl->status_mode == ESD_REG)
- ctrl->check_status = msm_dsi_reg_status_check;
- else if (ctrl->status_mode == ESD_BTA)
- ctrl->check_status = msm_dsi_bta_status_check;
- if (ctrl->status_mode == ESD_MAX) {
- pr_err("%s: Using default BTA for ESD check\n", __func__);
- ctrl->check_status = msm_dsi_bta_status_check;
- }
- }
- static int __devinit msm_dsi_probe(struct platform_device *pdev)
- {
- struct dsi_interface intf;
- char panel_cfg[MDSS_MAX_PANEL_LEN];
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- int rc = 0;
- struct device_node *dsi_pan_node = NULL;
- bool cmd_cfg_cont_splash = false;
- struct resource *mdss_dsi_mres;
- pr_debug("%s\n", __func__);
- rc = msm_dsi_init();
- if (rc)
- return rc;
- if (!pdev->dev.of_node) {
- pr_err("%s: Device node is not accessible\n", __func__);
- rc = -ENODEV;
- goto error_no_mem;
- }
- pdev->id = 0;
- ctrl_pdata = platform_get_drvdata(pdev);
- if (!ctrl_pdata) {
- ctrl_pdata = devm_kzalloc(&pdev->dev,
- sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
- if (!ctrl_pdata) {
- pr_err("%s: FAILED: cannot alloc dsi ctrl\n", __func__);
- rc = -ENOMEM;
- goto error_no_mem;
- }
- platform_set_drvdata(pdev, ctrl_pdata);
- }
- mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mdss_dsi_mres) {
- pr_err("%s:%d unable to get the MDSS reg resources",
- __func__, __LINE__);
- rc = -ENOMEM;
- goto error_io_resource;
- } else {
- dsi_host_private->dsi_reg_size = resource_size(mdss_dsi_mres);
- dsi_host_private->dsi_base = ioremap(mdss_dsi_mres->start,
- dsi_host_private->dsi_reg_size);
- if (!dsi_host_private->dsi_base) {
- pr_err("%s:%d unable to remap dsi resources",
- __func__, __LINE__);
- rc = -ENOMEM;
- goto error_io_resource;
- }
- #if defined(CONFIG_FB_MSM_MDSS_DSI_DBG)
- dsi_ctrl_base = dsi_host_private->dsi_base;
- dsi_ctrl_on = dsi_host_private->dsi_on;
- #endif
- }
- mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!mdss_dsi_mres || mdss_dsi_mres->start == 0) {
- pr_err("%s:%d unable to get the MDSS irq resources",
- __func__, __LINE__);
- rc = -ENODEV;
- goto error_irq_resource;
- }
- rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
- if (rc) {
- dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
- __func__, rc);
- goto error_platform_pop;
- }
- /* DSI panels can be different between controllers */
- rc = dsi_get_panel_cfg(panel_cfg);
- if (!rc)
- /* dsi panel cfg not present */
- pr_warn("%s:%d:dsi specific cfg not present\n",
- __func__, __LINE__);
- /* find panel device node */
- dsi_pan_node = dsi_find_panel_of_node(pdev, panel_cfg);
- if (!dsi_pan_node) {
- pr_err("%s: can't find panel node %s\n", __func__,
- panel_cfg);
- goto error_pan_node;
- }
- cmd_cfg_cont_splash = mdp3_panel_get_boot_cfg() ? true : false;
- rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
- if (rc) {
- pr_err("%s: dsi panel init failed\n", __func__);
- goto error_pan_node;
- }
- rc = dsi_ctrl_config_init(pdev, ctrl_pdata);
- if (rc) {
- dev_err(&pdev->dev, "%s: failed to parse mdss dtsi rc=%d\n",
- __func__, rc);
- goto error_pan_node;
- }
- rc = msm_dsi_io_init(pdev, &(ctrl_pdata->power_data));
- if (rc) {
- dev_err(&pdev->dev, "%s: failed to init DSI IO, rc=%d\n",
- __func__, rc);
- goto error_io_init;
- }
- pr_debug("%s: Dsi Ctrl->0 initialized\n", __func__);
- dsi_host_private->dis_dev = pdev->dev;
- intf.on = msm_dsi_on;
- intf.off = msm_dsi_off;
- intf.cont_on = msm_dsi_cont_on;
- intf.clk_ctrl = msm_dsi_clk_ctrl;
- intf.op_mode_config = msm_dsi_op_mode_config;
- intf.index = 0;
- intf.private = NULL;
- dsi_register_interface(&intf);
- msm_dsi_debug_init();
- msm_dsi_ctrl_init(ctrl_pdata);
- rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start,
- ctrl_pdata);
- if (rc) {
- dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
- __func__, rc);
- goto error_device_register;
- }
- rc = dsi_panel_device_register_v2(pdev, ctrl_pdata);
- if (rc) {
- pr_err("%s: dsi panel dev reg failed\n", __func__);
- goto error_device_register;
- }
- pr_debug("%s success\n", __func__);
- return 0;
- error_device_register:
- msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
- error_io_init:
- dsi_ctrl_config_deinit(pdev, ctrl_pdata);
- error_pan_node:
- of_node_put(dsi_pan_node);
- error_platform_pop:
- msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
- error_irq_resource:
- if (dsi_host_private->dsi_base) {
- iounmap(dsi_host_private->dsi_base);
- dsi_host_private->dsi_base = NULL;
- }
- error_io_resource:
- devm_kfree(&pdev->dev, ctrl_pdata);
- error_no_mem:
- msm_dsi_deinit();
- return rc;
- }
- static int __devexit msm_dsi_remove(struct platform_device *pdev)
- {
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
- if (!ctrl_pdata) {
- pr_err("%s: no driver data\n", __func__);
- return -ENODEV;
- }
- msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
- msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
- dsi_ctrl_config_deinit(pdev, ctrl_pdata);
- iounmap(dsi_host_private->dsi_base);
- dsi_host_private->dsi_base = NULL;
- msm_dsi_deinit();
- devm_kfree(&pdev->dev, ctrl_pdata);
- return 0;
- }
- static const struct of_device_id msm_dsi_v2_dt_match[] = {
- {.compatible = "qcom,msm-dsi-v2"},
- {}
- };
- MODULE_DEVICE_TABLE(of, msm_dsi_v2_dt_match);
- static struct platform_driver msm_dsi_v2_driver = {
- .probe = msm_dsi_probe,
- .remove = __devexit_p(msm_dsi_remove),
- .shutdown = NULL,
- .driver = {
- .name = "msm_dsi_v2",
- .of_match_table = msm_dsi_v2_dt_match,
- },
- };
- static int msm_dsi_v2_register_driver(void)
- {
- return platform_driver_register(&msm_dsi_v2_driver);
- }
- static int __init msm_dsi_v2_driver_init(void)
- {
- int ret;
- ret = msm_dsi_v2_register_driver();
- if (ret) {
- pr_err("msm_dsi_v2_register_driver() failed!\n");
- return ret;
- }
- return ret;
- }
- module_init(msm_dsi_v2_driver_init);
- static void __exit msm_dsi_v2_driver_cleanup(void)
- {
- platform_driver_unregister(&msm_dsi_v2_driver);
- }
- module_exit(msm_dsi_v2_driver_cleanup);
|