123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524 |
- /* Copyright (c) 2013, 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/kernel.h>
- #include <linux/sched.h>
- #include <linux/time.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/spinlock.h>
- #include <linux/delay.h>
- #include <linux/io.h>
- #include <linux/semaphore.h>
- #include <linux/uaccess.h>
- #include <linux/clk.h>
- #include <linux/platform_device.h>
- #include <linux/bug.h>
- #include <linux/of_gpio.h>
- #include <asm/system.h>
- #include <asm/mach-types.h>
- #include <mach/hardware.h>
- #include <mach/gpio.h>
- #include <mach/clk.h>
- #include <mach/dma.h>
- #include "mdss_panel.h"
- #include "mdss_edp.h"
- /*
- * edp buffer operation
- */
- #if defined(CONFIG_FB_MSM_EDP_SAMSUNG)
- static struct mdss_edp_drv_pdata *g_ep;
- void set_global_ep(struct mdss_edp_drv_pdata *ep)
- {
- g_ep = ep;
- }
- struct mdss_edp_drv_pdata *get_global_ep(void)
- {
- return g_ep;
- }
- #endif
- static char *edp_buf_init(struct edp_buf *eb, char *buf, int size)
- {
- eb->start = buf;
- eb->size = size;
- eb->data = eb->start;
- eb->end = eb->start + eb->size;
- eb->len = 0;
- eb->trans_num = 0;
- eb->i2c = 0;
- return eb->data;
- }
- static char *edp_buf_reset(struct edp_buf *eb)
- {
- eb->data = eb->start;
- eb->len = 0;
- eb->trans_num = 0;
- eb->i2c = 0;
- return eb->data;
- }
- static char *edp_buf_push(struct edp_buf *eb, int len)
- {
- eb->data += len;
- eb->len += len;
- return eb->data;
- }
- static int edp_buf_trailing(struct edp_buf *eb)
- {
- return (int)(eb->end - eb->data);
- }
- /*
- * edp aux edp_buf_add_cmd:
- * NO native and i2c command mix allowed
- */
- static int edp_buf_add_cmd(struct edp_buf *eb, struct edp_cmd *cmd)
- {
- char data;
- char *bp, *cp;
- int i, len;
- if (cmd->read) /* read */
- len = 4;
- else
- len = cmd->len + 4;
- if (edp_buf_trailing(eb) < len)
- return 0;
- /*
- * cmd fifo only has depth of 144 bytes
- * limit buf length to 128 bytes here
- */
- if ((eb->len + len) > 128)
- return 0;
- bp = eb->data;
- data = cmd->addr >> 16;
- data &= 0x0f; /* 4 addr bits */
- if (cmd->read)
- data |= BIT(4);
- *bp++ = data;
- *bp++ = cmd->addr >> 8;
- *bp++ = cmd->addr;
- *bp++ = cmd->len - 1;
- if (!cmd->read) { /* write */
- cp = cmd->datap;
- for (i = 0; i < cmd->len; i++)
- *bp++ = *cp++;
- }
- edp_buf_push(eb, len);
- if (cmd->i2c)
- eb->i2c++;
- eb->trans_num++; /* Increase transaction number */
- return cmd->len - 1;
- }
- static int edp_cmd_fifo_tx(struct edp_buf *tp, unsigned char *base)
- {
- u32 data;
- char *dp;
- int len, cnt;
- u32 reg;
- len = tp->len; /* total byte to cmd fifo */
- if (len == 0)
- return 0;
- cnt = 0;
- dp = tp->start;
- while (cnt < len) {
- data = *dp; /* data byte */
- data <<= 8;
- data &= 0x00ff00; /* index = 0, write */
- if (cnt == 0)
- data |= BIT(31); /* INDEX_WRITE */
- pr_debug("%s: data=%x\n", __func__, data);
- edp_write(base + EDP_AUX_DATA, data);
- cnt++;
- dp++;
- }
- data = (tp->trans_num - 1);
- if (tp->i2c)
- data |= BIT(8); /* I2C */
- /* To clear BIT(9) GO bit */
- reg = edp_read(base + EDP_AUX_TRANS_CTRL);
- edp_write(base + EDP_AUX_TRANS_CTRL, reg & (~(0x1 << 9)));
- data |= BIT(9); /* GO */
- pr_debug("%s: data=%x\n", __func__, data);
- edp_write(base + EDP_AUX_TRANS_CTRL, data);
- return tp->len;
- }
- static int edp_cmd_fifo_rx(struct edp_buf *rp, int len, unsigned char *base)
- {
- u32 data;
- char *dp;
- int i;
- data = 0; /* index = 0 */
- data |= BIT(31); /* INDEX_WRITE */
- data |= BIT(0); /* read */
- edp_write(base + EDP_AUX_DATA, data);
- dp = rp->data;
- /* discard first byte */
- data = edp_read(base + EDP_AUX_DATA);
- for (i = 0; i < len; i++) {
- data = edp_read(base + EDP_AUX_DATA);
- pr_debug("%s: data=%x\n", __func__, data);
- *dp++ = (char)((data >> 8) & 0xff);
- }
- rp->len = len;
- return len;
- }
- static int edp_aux_write_cmds(struct mdss_edp_drv_pdata *ep,
- struct edp_cmd *cmd)
- {
- struct edp_cmd *cm;
- struct edp_buf *tp;
- int len, ret;
- mutex_lock(&ep->aux_mutex);
- ep->aux_cmd_busy = 1;
- tp = &ep->txp;
- edp_buf_reset(tp);
- cm = cmd;
- while (cm) {
- pr_debug("%s: i2c=%d read=%d addr=%x len=%d next=%d\n",
- __func__, cm->i2c, cm->read, cm->addr, cm->len,
- cm->next);
- ret = edp_buf_add_cmd(tp, cm);
- if (ret <= 0)
- break;
- if (cm->next == 0)
- break;
- cm++;
- }
- if (tp->i2c)
- ep->aux_cmd_i2c = 1;
- else
- ep->aux_cmd_i2c = 0;
- INIT_COMPLETION(ep->aux_comp);
- len = edp_cmd_fifo_tx(&ep->txp, ep->base);
- wait_for_completion(&ep->aux_comp);
- if (ep->aux_error_num == EDP_AUX_ERR_NONE)
- ret = len;
- else
- ret = ep->aux_error_num;
- ep->aux_cmd_busy = 0;
- mutex_unlock(&ep->aux_mutex);
- return ret;
- }
- static int edp_aux_read_cmds(struct mdss_edp_drv_pdata *ep,
- struct edp_cmd *cmds)
- {
- struct edp_cmd *cm;
- struct edp_buf *tp;
- struct edp_buf *rp;
- int len, ret;
- mutex_lock(&ep->aux_mutex);
- ep->aux_cmd_busy = 1;
- tp = &ep->txp;
- rp = &ep->rxp;
- edp_buf_reset(tp);
- edp_buf_reset(rp);
- cm = cmds;
- len = 0;
- while (cm) {
- pr_debug("%s: i2c=%d read=%d addr=%x len=%d next=%d\n",
- __func__, cm->i2c, cm->read, cm->addr, cm->len,
- cm->next);
- ret = edp_buf_add_cmd(tp, cm);
- len += cm->len;
- if (ret <= 0)
- break;
- if (cm->next == 0)
- break;
- cm++;
- }
- if (tp->i2c)
- ep->aux_cmd_i2c = 1;
- else
- ep->aux_cmd_i2c = 0;
- INIT_COMPLETION(ep->aux_comp);
- edp_cmd_fifo_tx(tp, ep->base);
- wait_for_completion(&ep->aux_comp);
- if (ep->aux_error_num == EDP_AUX_ERR_NONE)
- ret = edp_cmd_fifo_rx(rp, len, ep->base);
- else
- ret = ep->aux_error_num;
- ep->aux_cmd_busy = 0;
- mutex_unlock(&ep->aux_mutex);
- return ret;
- }
- void edp_aux_native_handler(struct mdss_edp_drv_pdata *ep, u32 isr)
- {
- pr_debug("%s: isr=%x\n", __func__, isr);
- if (isr & EDP_INTR_AUX_I2C_DONE) {
- ep->aux_error_num = EDP_AUX_ERR_NONE;
- }
- else if (isr & EDP_INTR_WRONG_ADDR) {
- ep->aux_error_num = EDP_AUX_ERR_ADDR;
- pr_err("%s: isr=%x\n", __func__, isr);
- }
- else if (isr & EDP_INTR_TIMEOUT) {
- ep->aux_error_num = EDP_AUX_ERR_TOUT;
- pr_err("%s: isr=%x\n", __func__, isr);
- }
- if (isr & EDP_INTR_NACK_DEFER) {
- ep->aux_error_num = EDP_AUX_ERR_NACK;
- pr_err("%s: isr=%x\n", __func__, isr);
- }
- complete(&ep->aux_comp);
- }
- void edp_aux_i2c_handler(struct mdss_edp_drv_pdata *ep, u32 isr)
- {
- pr_debug("%s: isr=%x\n", __func__, isr);
- if (isr & EDP_INTR_AUX_I2C_DONE) {
- if (isr & (EDP_INTR_I2C_NACK | EDP_INTR_I2C_DEFER))
- ep->aux_error_num = EDP_AUX_ERR_NACK;
- else
- ep->aux_error_num = EDP_AUX_ERR_NONE;
- } else {
- if (isr & EDP_INTR_WRONG_ADDR)
- ep->aux_error_num = EDP_AUX_ERR_ADDR;
- else if (isr & EDP_INTR_TIMEOUT)
- ep->aux_error_num = EDP_AUX_ERR_TOUT;
- if (isr & EDP_INTR_NACK_DEFER)
- ep->aux_error_num = EDP_AUX_ERR_NACK;
- if (isr & EDP_INTR_I2C_NACK)
- ep->aux_error_num = EDP_AUX_ERR_NACK;
- if (isr & EDP_INTR_I2C_DEFER)
- ep->aux_error_num = EDP_AUX_ERR_NACK;
- }
- complete(&ep->aux_comp);
- }
- static int edp_aux_write_buf(struct mdss_edp_drv_pdata *ep, u32 addr,
- char *buf, int len, int i2c)
- {
- struct edp_cmd cmd;
- cmd.read = 0;
- cmd.i2c = i2c;
- cmd.addr = addr;
- cmd.datap = buf;
- cmd.len = len & 0x0ff;
- cmd.next = 0;
- return edp_aux_write_cmds(ep, &cmd);
- }
- static int edp_aux_read_buf(struct mdss_edp_drv_pdata *ep, u32 addr,
- int len, int i2c)
- {
- struct edp_cmd cmd;
- cmd.read = 1;
- cmd.i2c = i2c;
- cmd.addr = addr;
- cmd.datap = NULL;
- cmd.len = len & 0x0ff;
- cmd.next = 0;
- return edp_aux_read_cmds(ep, &cmd);
- }
- /*
- * edid standard header bytes
- */
- static char edid_hdr[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
- int edp_edid_buf_error(char *buf, int len)
- {
- char *bp;
- int i;
- char csum = 0;
- bp = buf;
- if (len < 128) {
- pr_err("%s: Error: len=%x\n", __func__, len);
- return -EINVAL;
- }
- for (i = 0; i < 128; i++)
- csum += *bp++;
- if (csum != 0) {
- pr_err("%s: Error: csum=%x\n", __func__, csum);
- return -EINVAL;
- }
- if (strncmp(buf, edid_hdr, strlen(edid_hdr))) {
- pr_err("%s: Error: header\n", __func__);
- return -EINVAL;
- }
- return 0;
- }
- void edp_extract_edid_manufacturer(struct edp_edid *edid, char *buf)
- {
- char *bp;
- char data;
- bp = &buf[8];
- data = *bp & 0x7f;
- data >>= 2;
- edid->id_name[0] = 'A' + data - 1;
- data = *bp & 0x03;
- data <<= 3;
- bp++;
- data |= (*bp >> 5);
- edid->id_name[1] = 'A' + data - 1;
- data = *bp & 0x1f;
- edid->id_name[2] = 'A' + data - 1;
- edid->id_name[3] = 0;
- pr_info("%s: edid manufacturer = %s\n", __func__, edid->id_name);
- }
- void edp_extract_edid_product(struct edp_edid *edid, char *buf)
- {
- char *bp;
- u32 data;
- bp = &buf[0x0a];
- data = *bp;
- edid->id_product = *bp++;
- edid->id_product &= 0x0ff;
- data = *bp & 0x0ff;
- data <<= 8;
- edid->id_product |= data;
- pr_info("%s: edid product = 0x%x\n", __func__, edid->id_product);
- };
- void edp_extract_edid_version(struct edp_edid *edid, char *buf)
- {
- edid->version = buf[0x12];
- edid->revision = buf[0x13];
- pr_info("%s: edid version = %d.%d\n", __func__, edid->version,
- edid->revision);
- };
- void edp_extract_edid_ext_block_cnt(struct edp_edid *edid, char *buf)
- {
- edid->ext_block_cnt = buf[0x7e];
- pr_debug("%s: edid extension = %d\n", __func__,
- edid->ext_block_cnt);
- };
- void edp_extract_edid_video_support(struct edp_edid *edid, char *buf)
- {
- char *bp;
- bp = &buf[0x14];
- if (*bp & 0x80) {
- edid->video_intf = *bp & 0x0f;
- /* 6, 8, 10, 12, 14 and 16 bit per component */
- edid->color_depth = ((*bp & 0x70) >> 4); /* color bit depth */
- if (edid->color_depth) {
- edid->color_depth *= 2;
- edid->color_depth += 4;
- }
- pr_debug("%s: Digital Video intf=%d color_depth=%d\n",
- __func__, edid->video_intf, edid->color_depth);
- } else {
- pr_err("%s: Error, Analog video interface\n", __func__);
- }
- };
- void edp_extract_edid_feature(struct edp_edid *edid, char *buf)
- {
- char *bp;
- char data;
- bp = &buf[0x18];
- data = *bp;
- data &= 0xe0;
- data >>= 5;
- if (data == 0x01)
- edid->dpm = 1; /* display power management */
- if (edid->video_intf) {
- if (*bp & 0x80) {
- /* RGB 4:4:4, YcrCb 4:4:4 and YCrCb 4:2:2 */
- edid->color_format = *bp & 0x18;
- edid->color_format >>= 3;
- }
- }
- pr_debug("%s: edid dpm=%d color_format=%d\n", __func__,
- edid->dpm, edid->color_format);
- };
- void edp_extract_edid_detailed_timing_description(struct edp_edid *edid,
- char *buf)
- {
- char *bp;
- u32 data;
- struct display_timing_desc *dp;
- dp = &edid->timing[0];
- bp = &buf[0x36];
- dp->pclk = 0;
- dp->pclk = *bp++; /* byte 0x36 */
- dp->pclk |= (*bp++ << 8); /* byte 0x37 */
- dp->h_addressable = *bp++; /* byte 0x38 */
- if (dp->pclk == 0 && dp->h_addressable == 0)
- return; /* Not detailed timing definition */
- dp->pclk *= 10000;
- dp->h_blank = *bp++;/* byte 0x39 */
- data = *bp & 0xf0; /* byte 0x3A */
- data <<= 4;
- dp->h_addressable |= data;
- data = *bp++ & 0x0f;
- data <<= 8;
- dp->h_blank |= data;
- dp->v_addressable = *bp++; /* byte 0x3B */
- dp->v_blank = *bp++; /* byte 0x3C */
- data = *bp & 0xf0; /* byte 0x3D */
- data <<= 4;
- dp->v_addressable |= data;
- data = *bp++ & 0x0f;
- data <<= 8;
- dp->v_blank |= data;
- dp->h_fporch = *bp++; /* byte 0x3E */
- dp->h_sync_pulse = *bp++; /* byte 0x3F */
- dp->v_fporch = *bp & 0x0f0; /* byte 0x40 */
- dp->v_fporch >>= 4;
- dp->v_sync_pulse = *bp & 0x0f;
- bp++;
- data = *bp & 0xc0; /* byte 0x41 */
- data <<= 2;
- dp->h_fporch |= data;
- data = *bp & 0x30;
- data <<= 4;
- dp->h_sync_pulse |= data;
- data = *bp & 0x0c;
- data <<= 2;
- dp->v_fporch |= data;
- data = *bp & 0x03;
- data <<= 4;
- dp->v_sync_pulse |= data;
- bp++;
- dp->width_mm = *bp++; /* byte 0x42 */
- dp->height_mm = *bp++; /* byte 0x43 */
- data = *bp & 0x0f0; /* byte 0x44 */
- data <<= 4;
- dp->width_mm |= data;
- data = *bp & 0x0f;
- data <<= 8;
- dp->height_mm |= data;
- bp++;
- dp->h_border = *bp++; /* byte 0x45 */
- dp->v_border = *bp++; /* byte 0x46 */
- /* progressive or interlaved */
- dp->interlaced = *bp & 0x80; /* byte 0x47 */
- dp->stereo = *bp & 0x60;
- dp->stereo >>= 5;
- data = *bp & 0x1e; /* bit 4,3,2 1*/
- data >>= 1;
- dp->sync_type = data & 0x08;
- dp->sync_type >>= 3; /* analog or digital */
- if (dp->sync_type) {
- dp->sync_separate = data & 0x04;
- dp->sync_separate >>= 2;
- if (dp->sync_separate) {
- if (data & 0x02)
- dp->vsync_pol = 1; /* positive */
- else
- dp->vsync_pol = 0;/* negative */
- if (data & 0x01)
- dp->hsync_pol = 1; /* positive */
- else
- dp->hsync_pol = 0; /* negative */
- }
- }
- pr_info("%s: pixel_clock = %d\n", __func__, dp->pclk);
- pr_info("%s: horizontal=%d, blank=%d, porch=%d, sync=%d\n"
- , __func__, dp->h_addressable, dp->h_blank,
- dp->h_fporch, dp->h_sync_pulse);
- pr_info("%s: vertical=%d, blank=%d, porch=%d, vsync=%d\n"
- , __func__, dp->v_addressable, dp->v_blank,
- dp->v_fporch, dp->v_sync_pulse);
- pr_info("%s: panel size in mm, width=%d height=%d\n", __func__,
- dp->width_mm, dp->height_mm);
- pr_info("%s: panel border horizontal=%d vertical=%d\n", __func__,
- dp->h_border, dp->v_border);
- pr_info("%s: flags: interlaced=%d stereo=%d sync_type=%d sync_sep=%d\n"
- , __func__, dp->interlaced, dp->stereo,
- dp->sync_type, dp->sync_separate);
- pr_info("%s: polarity vsync=%d, hsync=%d", __func__,
- dp->vsync_pol, dp->hsync_pol);
- }
- /*
- * EDID structure can be found in VESA standart here:
- * http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf
- *
- * following table contains default edid
- * static char edid_raw_data[128] = {
- * 0, 255, 255, 255, 255, 255, 255, 0,
- * 6, 175, 93, 48, 0, 0, 0, 0, 0, 22,
- * 1, 4,
- * 149, 26, 14, 120, 2,
- * 164, 21,158, 85, 78, 155, 38, 15, 80, 84,
- * 0, 0, 0,
- * 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- * 29, 54, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
- * 19, 36, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
- * 0, 0, 0, 254, 0, 65, 85, 79, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- * 0, 0, 0, 254, 0, 66, 49, 49, 54, 72, 65, 78, 48, 51, 46, 48, 32, 10,
- * 0, 75 };
- */
- static int edp_aux_chan_ready(struct mdss_edp_drv_pdata *ep)
- {
- #if defined(CONFIG_FB_MSM_EDP_SAMSUNG)
- return 1;
- #else
- int cnt, ret;
- char data = 0;
- for (cnt = 5; cnt; cnt--) {
- ret = edp_aux_write_buf(ep, 0x50, &data, 1, 1);
- pr_debug("%s: ret=%d\n", __func__, ret);
- if (ret >= 0)
- break;
- msleep(100);
- }
- if (cnt <= 0) {
- pr_err("%s: aux chan NOT ready\n", __func__);
- return 0;
- }
- return 1;
- #endif
- }
- static int edp_sink_edid_read(struct mdss_edp_drv_pdata *ep, int block)
- {
- struct edp_buf *rp;
- int cnt, rlen;
- int ret = 0;
- ret = edp_aux_chan_ready(ep);
- if (ret == 0) {
- pr_err("%s: aux chan NOT ready\n", __func__);
- return ret;
- }
- for (cnt = 5; cnt; cnt--) {
- rlen = edp_aux_read_buf(ep, 0x50, 128, 1);
- if (rlen > 0) {
- pr_debug("%s: rlen=%d\n", __func__, rlen);
- rp = &ep->rxp;
- if (!edp_edid_buf_error(rp->data, rp->len))
- break;
- }
- }
- if (cnt <= 0) {
- pr_err("%s: Failed\n", __func__);
- return -EINVAL;
- }
- edp_extract_edid_manufacturer(&ep->edid, rp->data);
- edp_extract_edid_product(&ep->edid, rp->data);
- edp_extract_edid_version(&ep->edid, rp->data);
- edp_extract_edid_ext_block_cnt(&ep->edid, rp->data);
- edp_extract_edid_video_support(&ep->edid, rp->data);
- edp_extract_edid_feature(&ep->edid, rp->data);
- edp_extract_edid_detailed_timing_description(&ep->edid, rp->data);
- return 128;
- }
- static void edp_sink_capability_read(struct mdss_edp_drv_pdata *ep,
- int len)
- {
- char *bp;
- char data;
- struct dpcd_cap *cap;
- struct edp_buf *rp;
- int rlen;
- rlen = edp_aux_read_buf(ep, 0, len, 0);
- if (rlen <= 0) {
- pr_err("%s: edp aux read failed\n", __func__);
- return;
- }
- rp = &ep->rxp;
- cap = &ep->dpcd;
- bp = rp->data;
- data = *bp++; /* byte 0 */
- cap->major = (data >> 4) & 0x0f;
- cap->minor = data & 0x0f;
- if (--rlen <= 0)
- return;
- pr_debug("%s: version: %d.%d\n", __func__, cap->major, cap->minor);
- data = *bp++; /* byte 1 */
- /* 162, 270 and 540 MB, symbol rate, NOT bit rate */
- cap->max_link_rate = data;
- if (--rlen <= 0)
- return;
- pr_info("%s: link_rate=%d\n", __func__, cap->max_link_rate);
- data = *bp++; /* byte 2 */
- if (data & BIT(7))
- cap->enhanced_frame++;
- if (data & 0x40)
- cap->flags |= DPCD_TPS3;
- data &= 0x0f;
- cap->max_lane_count = data;
- if (--rlen <= 0)
- return;
- pr_debug("%s: lane_count=%d\n", __func__, cap->max_lane_count);
- data = *bp++; /* byte 3 */
- if (data & BIT(0)) {
- cap->flags |= DPCD_MAX_DOWNSPREAD_0_5;
- pr_debug("%s: max_downspread\n", __func__);
- }
- if (data & BIT(6)) {
- cap->flags |= DPCD_NO_AUX_HANDSHAKE;
- pr_debug("%s: NO Link Training\n", __func__);
- }
- if (--rlen <= 0)
- return;
- data = *bp++; /* byte 4 */
- cap->num_rx_port = (data & BIT(0)) + 1;
- pr_debug("%s: rx_ports=%d", __func__, cap->num_rx_port);
- if (--rlen <= 0)
- return;
- bp += 3; /* skip 5, 6 and 7 */
- rlen -= 3;
- if (rlen <= 0)
- return;
- data = *bp++; /* byte 8 */
- if (data & BIT(1)) {
- cap->flags |= DPCD_PORT_0_EDID_PRESENTED;
- pr_debug("%s: edid presented\n", __func__);
- }
- if (--rlen <= 0)
- return;
- data = *bp++; /* byte 9 */
- cap->rx_port0_buf_size = (data + 1) * 32;
- pr_debug("%s: lane_buf_size=%d", __func__, cap->rx_port0_buf_size);
- if (--rlen <= 0)
- return;
- bp += 2; /* skip 10, 11 port1 capability */
- rlen -= 2;
- if (rlen <= 0)
- return;
- data = *bp++; /* byte 12 */
- cap->i2c_speed_ctrl = data;
- if (cap->i2c_speed_ctrl > 0)
- pr_debug("%s: i2c_rate=%d", __func__, cap->i2c_speed_ctrl);
- if (--rlen <= 0)
- return;
- data = *bp++; /* byte 13 */
- cap->scrambler_reset = data & BIT(0);
- pr_debug("%s: scrambler_reset=%d\n", __func__,
- cap->scrambler_reset);
- if (data & BIT(1))
- cap->enhanced_frame++;
- pr_debug("%s: enhanced_framing=%d\n", __func__,
- cap->enhanced_frame);
- if (--rlen <= 0)
- return;
- data = *bp++; /* byte 14 */
- if (data == 0)
- cap->training_read_interval = 4000; /* us */
- else
- cap->training_read_interval = 4000 * data; /* us */
- pr_debug("%s: training_interval=%d\n", __func__,
- cap->training_read_interval);
- }
- static int edp_link_status_read(struct mdss_edp_drv_pdata *ep, int len)
- {
- char *bp;
- char data;
- struct dpcd_link_status *sp;
- struct edp_buf *rp;
- int rlen;
- pr_debug("%s: len=%d", __func__, len);
- /* skip byte 0x200 and 0x201 */
- rlen = edp_aux_read_buf(ep, 0x202, len, 0);
- if (rlen < len) {
- pr_err("%s: edp aux read failed\n", __func__);
- return 0;
- }
- rp = &ep->rxp;
- bp = rp->data;
- sp = &ep->link_status;
- data = *bp++; /* byte 0x202 */
- sp->lane_01_status = data; /* lane 0, 1 */
- data = *bp++; /* byte 0x203 */
- sp->lane_23_status = data; /* lane 2, 3 */
- data = *bp++; /* byte 0x204 */
- sp->interlane_align_done = (data & BIT(0));
- sp->downstream_port_status_changed = (data & BIT(6));
- sp->link_status_updated = (data & BIT(7));
- data = *bp++; /* byte 0x205 */
- sp->port_0_in_sync = (data & BIT(0));
- sp->port_1_in_sync = (data & BIT(1));
- data = *bp++; /* byte 0x206 */
- sp->req_voltage_swing[0] = data & 0x03;
- data >>= 2;
- sp->req_pre_emphasis[0] = data & 0x03;
- data >>= 2;
- sp->req_voltage_swing[1] = data & 0x03;
- data >>= 2;
- sp->req_pre_emphasis[1] = data & 0x03;
- data = *bp++; /* byte 0x207 */
- sp->req_voltage_swing[2] = data & 0x03;
- data >>= 2;
- sp->req_pre_emphasis[2] = data & 0x03;
- data >>= 2;
- sp->req_voltage_swing[3] = data & 0x03;
- data >>= 2;
- sp->req_pre_emphasis[3] = data & 0x03;
- return len;
- }
- static int edp_cap_lane_rate_set(struct mdss_edp_drv_pdata *ep)
- {
- char buf[4];
- int len = 0;
- struct dpcd_cap *cap;
- cap = &ep->dpcd;
- pr_debug("%s: bw=%x lane=%d\n", __func__, ep->link_rate, ep->lane_cnt);
- buf[0] = ep->link_rate;
- buf[1] = ep->lane_cnt;
- if (cap->enhanced_frame)
- buf[1] |= 0x80;
- len = edp_aux_write_buf(ep, 0x100, buf, 2, 0);
- return len;
- }
- static int edp_lane_set_write(struct mdss_edp_drv_pdata *ep, int voltage_level,
- int pre_emphasis_level)
- {
- int i;
- char buf[4];
- if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
- voltage_level |= 0x04;
- if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
- pre_emphasis_level |= 0x04;
- pre_emphasis_level <<= 3;
- for (i = 0; i < 4; i++)
- buf[i] = voltage_level | pre_emphasis_level;
- pr_debug("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level);
- return edp_aux_write_buf(ep, 0x103, buf, 4, 0);
- }
- static int edp_train_pattern_set_write(struct mdss_edp_drv_pdata *ep,
- int pattern)
- {
- char buf[4];
- pr_debug("%s: pattern=%x\n", __func__, pattern);
- buf[0] = pattern;
- return edp_aux_write_buf(ep, 0x102, buf, 1, 0);
- }
- static int edp_sink_clock_recovery_done(struct mdss_edp_drv_pdata *ep)
- {
- u32 mask;
- u32 data;
- if (ep->lane_cnt == 1) {
- mask = 0x01; /* lane 0 */
- data = ep->link_status.lane_01_status;
- } else if (ep->lane_cnt == 2) {
- mask = 0x011; /*B lane 0, 1 */
- data = ep->link_status.lane_01_status;
- } else {
- mask = 0x01111; /*B lane 0, 1 */
- data = ep->link_status.lane_23_status;
- data <<= 8;
- data |= ep->link_status.lane_01_status;
- }
- pr_debug("%s: data=%x mask=%x\n", __func__, data, mask);
- data &= mask;
- if (data == mask) /* all done */
- return 1;
- return 0;
- }
- static int edp_sink_channel_eq_done(struct mdss_edp_drv_pdata *ep)
- {
- u32 mask;
- u32 data;
- pr_debug("%s:\n", __func__);
- if (!ep->link_status.interlane_align_done) { /* not align */
- pr_err("%s: interlane align failed\n", __func__);
- return 0;
- }
- if (ep->lane_cnt == 1) {
- mask = 0x7;
- data = ep->link_status.lane_01_status;
- } else if (ep->lane_cnt == 2) {
- mask = 0x77;
- data = ep->link_status.lane_01_status;
- } else {
- mask = 0x7777;
- data = ep->link_status.lane_23_status;
- data <<= 8;
- data |= ep->link_status.lane_01_status;
- }
- pr_debug("%s: data=%x mask=%x\n", __func__, data, mask);
- data &= mask;
- if (data == mask)/* all done */
- return 1;
- return 0;
- }
- void edp_sink_train_set_adjust(struct mdss_edp_drv_pdata *ep)
- {
- int i;
- int max = 0;
- /* use the max level across lanes */
- for (i = 0; i < ep->lane_cnt; i++) {
- pr_debug("%s: lane=%d req_voltage_swing=%d",
- __func__, i, ep->link_status.req_voltage_swing[i]);
- if (max < ep->link_status.req_voltage_swing[i])
- max = ep->link_status.req_voltage_swing[i];
- }
- ep->v_level = max;
- /* use the max level across lanes */
- max = 0;
- for (i = 0; i < ep->lane_cnt; i++) {
- pr_debug(" %s: lane=%d req_pre_emphasis=%d",
- __func__, i, ep->link_status.req_pre_emphasis[i]);
- if (max < ep->link_status.req_pre_emphasis[i])
- max = ep->link_status.req_pre_emphasis[i];
- }
- ep->p_level = max;
- pr_debug("%s: v_level=%d, p_level=%d", __func__,
- ep->v_level, ep->p_level);
- }
- static void edp_host_train_set(struct mdss_edp_drv_pdata *ep, int train)
- {
- int bit, cnt;
- u32 data;
- bit = 1;
- bit <<= (train - 1);
- pr_debug("%s: bit=%d train=%d\n", __func__, bit, train);
- edp_write(ep->base + EDP_STATE_CTRL, bit);
- bit = 8;
- bit <<= (train - 1);
- cnt = 10;
- while (cnt--) {
- data = edp_read(ep->base + EDP_MAINLINK_READY);
- if (data & bit)
- break;
- }
- if (cnt == 0)
- pr_err("%s: set link_train=%d failed\n", __func__, train);
- }
- char vm_pre_emphasis[4][4] = {
- {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */
- {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */
- {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */
- {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
- };
- /* voltage swing, 0.2v and 1.0v are not support */
- char vm_voltage_swing[4][4] = {
- {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */
- {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */
- {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */
- {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
- };
- static void edp_voltage_pre_emphasise_set(struct mdss_edp_drv_pdata *ep)
- {
- u32 value0 = 0;
- u32 value1 = 0;
- pr_debug("%s: v=%d p=%d\n", __func__, ep->v_level, ep->p_level);
- value0 = vm_pre_emphasis[(int)(ep->v_level)][(int)(ep->p_level)];
- value1 = vm_voltage_swing[(int)(ep->v_level)][(int)(ep->p_level)];
- /* Configure host and panel only if both values are allowed */
- if (value0 != 0xFF && value1 != 0xFF) {
- edp_write(ep->base + EDP_PHY_EDPPHY_GLB_VM_CFG0, value0);
- edp_write(ep->base + EDP_PHY_EDPPHY_GLB_VM_CFG1, value1);
- pr_debug("%s: value0=0x%x value1=0x%x", __func__,
- value0, value1);
- edp_lane_set_write(ep, ep->v_level, ep->p_level);
- }
- }
- static int edp_start_link_train_1(struct mdss_edp_drv_pdata *ep)
- {
- int tries, old_v_level;
- int ret = 0;
- pr_debug("%s:", __func__);
- edp_host_train_set(ep, 0x01); /* train_1 */
- edp_voltage_pre_emphasise_set(ep);
- edp_train_pattern_set_write(ep, 0x21); /* train_1 */
- tries = 0;
- old_v_level = ep->v_level;
- while (1) {
- usleep(ep->dpcd.training_read_interval);
- if (edp_read(ep->base + EDP_MAINLINK_READY) & BIT(3))
- pr_debug("%s: Training pattern 1 was sent properly\n", __func__);
- else
- pr_err("%s: Error in sending training pattern 1 value : 0x%x\n", __func__, edp_read(ep->base + EDP_MAINLINK_READY) );
- edp_link_status_read(ep, 6);
- if (edp_sink_clock_recovery_done(ep)) {
- ret = 0;
- break;
- }
- if (ep->v_level == DPCD_LINK_VOLTAGE_MAX) {
- ret = -1;
- break; /* quit */
- }
- if (old_v_level == ep->v_level) {
- tries++;
- if (tries >= 5) {
- ret = -1;
- break; /* quit */
- }
- } else {
- tries = 0;
- old_v_level = ep->v_level;
- }
- edp_sink_train_set_adjust(ep);
- edp_voltage_pre_emphasise_set(ep);
- }
- return ret;
- }
- static int edp_start_link_train_2(struct mdss_edp_drv_pdata *ep)
- {
- int tries;
- int ret = 0;
- char pattern;
- pr_debug("%s:", __func__);
- if (ep->dpcd.flags & DPCD_TPS3)
- pattern = 0x03;
- else
- pattern = 0x02;
- edp_host_train_set(ep, pattern); /* train_2 */
- edp_voltage_pre_emphasise_set(ep);
- edp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
- tries = 0;
- while (1) {
- usleep(ep->dpcd.training_read_interval);
- if (edp_read(ep->base + 0x84) & BIT(4))
- pr_debug("%s: Training pattern 2 was sent properly\n", __func__);
- else
- pr_err("%s: Error in sending training pattern 2\n", __func__);
- edp_link_status_read(ep, 6);
- if (edp_sink_channel_eq_done(ep)) {
- ret = 0;
- break;
- }
- tries++;
- if (tries > 5) {
- ret = -1;
- break;
- }
- edp_sink_train_set_adjust(ep);
- edp_voltage_pre_emphasise_set(ep);
- }
- return ret;
- }
- static int edp_link_rate_down_shift(struct mdss_edp_drv_pdata *ep)
- {
- u32 prate, lrate;
- int rate, lane, max_lane;
- int changed = 0;
- rate = ep->link_rate;
- lane = ep->lane_cnt;
- max_lane = ep->dpcd.max_lane_count;
- prate = ep->pixel_rate;
- prate /= 1000; /* avoid using 64 biits */
- prate *= ep->bpp;
- prate /= 8; /* byte */
- #if !defined(CONFIG_FB_MSM_EDP_SAMSUNG)
- /*
- Link rate is fixed to 2.7G for eDP panel.
- */
- if (rate > EDP_LINK_RATE_162 && rate <= EDP_LINK_RATE_MAX) {
- rate -= 4; /* reduce rate */
- changed++;
- }
- #endif
- if (changed) {
- if (lane >= 1 && lane < max_lane)
- lane <<= 1; /* increase lane */
- lrate = 270000000; /* 270M */
- lrate /= 1000; /* avoid using 64 bits */
- lrate *= rate;
- lrate /= 10; /* byte, 10 bits --> 8 bits */
- lrate *= lane;
- pr_info("%s: new lrate=%u prate=%u rate=%d lane=%d p=%d b=%d\n",
- __func__, lrate, prate, rate, lane, ep->pixel_rate, ep->bpp);
- if (lrate > prate) {
- ep->link_rate = rate;
- ep->lane_cnt = lane;
- pr_info("%s: new rate=%d %d\n", __func__, rate, lane);
- return 0;
- }
- }
- /* add calculation later */
- return -EINVAL;
- }
- static void edp_clear_training_pattern(struct mdss_edp_drv_pdata *ep)
- {
- pr_debug("%s:\n", __func__);
- edp_train_pattern_set_write(ep, 0);
- usleep(ep->dpcd.training_read_interval);
- }
- static int edp_aux_link_train(struct mdss_edp_drv_pdata *ep)
- {
- int ret = 0;
- pr_info("%s", __func__);
- ep->dpcd.training_read_interval = 1000;
- ret = edp_aux_chan_ready(ep);
- if (ret == 0) {
- pr_err("%s: LINK Train failed: aux chan NOT ready\n", __func__);
- complete(&ep->train_comp);
- return ret;
- }
- edp_write(ep->base + EDP_MAINLINK_CTRL, 0x1);
- mdss_edp_sink_power_state(ep, SINK_POWER_ON);
- train_start:
- ep->v_level = 0; /* start from default level */
- ep->p_level = 0;
- edp_cap_lane_rate_set(ep);
- mdss_edp_config_ctrl(ep);
- mdss_edp_lane_power_ctrl(ep, 1);
- mdss_edp_state_ctrl(ep, 0);
- edp_clear_training_pattern(ep);
- usleep(ep->dpcd.training_read_interval);
- ret = edp_start_link_train_1(ep);
- if (ret < 0) {
- if (edp_link_rate_down_shift(ep) == 0) {
- goto train_start;
- } else {
- pr_err("%s: Training 1 failed", __func__);
- ret = -1;
- goto clear;
- }
- }
- pr_debug("%s: Training 1 completed successfully", __func__);
- mdss_edp_state_ctrl(ep, 0);
- /* recovery_done : 0x1111*/
- pr_info("%s: Training 1 completed successfully recovery_done : 0x%x", __func__,
- (ep->link_status.lane_23_status << 8) | ep->link_status.lane_01_status);
- #if !defined(CONFIG_FB_MSM_EDP_SAMSUNG)
- edp_clear_training_pattern(ep);
- #endif
- ret = edp_start_link_train_2(ep);
- if (ret < 0) {
- if (edp_link_rate_down_shift(ep) == 0) {
- goto train_start;
- } else {
- pr_err("%s: Training 2 failed", __func__);
- ret = -1;
- goto clear;
- }
- }
- /* recovery_done : 0x7777*/
- pr_info("%s: Training 2 completed successfully eq_done : 0x%x v_level : %d p_level : %d", __func__,
- (ep->link_status.lane_23_status << 8) | ep->link_status.lane_01_status, ep->v_level, ep->p_level);
- mdss_edp_state_ctrl(ep, ST_SEND_VIDEO);
- clear:
- edp_clear_training_pattern(ep);
- complete(&ep->train_comp);
- return ret;
- }
- void mdss_edp_dpcd_cap_read(struct mdss_edp_drv_pdata *ep)
- {
- edp_sink_capability_read(ep, 16);
- }
- int mdss_edp_dpcd_status_read(struct mdss_edp_drv_pdata *ep)
- {
- struct dpcd_link_status *sp;
- int ret = 0; /* not sync */
- ret = edp_link_status_read(ep, 6);
- if (ret) {
- sp = &ep->link_status;
- ret = sp->port_0_in_sync; /* 1 == sync */
- }
- return ret;
- }
- void mdss_edp_fill_link_cfg(struct mdss_edp_drv_pdata *ep)
- {
- struct display_timing_desc *dp;
- dp = &ep->edid.timing[0];
- ep->pixel_rate = dp->pclk;
- ep->lane_cnt = ep->dpcd.max_lane_count;
- ep->link_rate = ep->dpcd.max_link_rate;
- pr_debug("%s: pclk=%d rate=%d lane=%d\n", __func__,
- ep->pixel_rate, ep->link_rate, ep->lane_cnt);
- }
- void mdss_edp_edid_read(struct mdss_edp_drv_pdata *ep, int block)
- {
- edp_sink_edid_read(ep, block);
- }
- int mdss_edp_sink_power_state(struct mdss_edp_drv_pdata *ep, char state)
- {
- int ret;
- ret = edp_aux_write_buf(ep, 0x600, &state, 1, 0);
- pr_info("%s: state=%d ret=%d\n", __func__, state, ret);
- return ret;
- }
- int mdss_edp_link_train(struct mdss_edp_drv_pdata *ep)
- {
- int ret;
- mutex_lock(&ep->train_mutex);
- ret = edp_aux_link_train(ep);
- mutex_unlock(&ep->train_mutex);
- return ret;
- }
- void mdss_edp_aux_setup(struct mdss_edp_drv_pdata *ep)
- {
- mutex_init(&ep->aux_mutex);
- init_completion(&ep->aux_comp);
- edp_buf_init(&ep->txp, ep->txbuf, sizeof(ep->txbuf));
- edp_buf_init(&ep->rxp, ep->rxbuf, sizeof(ep->rxbuf));
- }
- #if defined(CONFIG_FB_MSM_EDP_SAMSUNG)
- int aux_tx(int addr, char *data, int len)
- {
- struct mdss_edp_drv_pdata *ep = get_global_ep();
- if (!ep) {
- pr_info("%s error", __func__);
- return -1;
- }
- return edp_aux_write_buf(ep, addr, data, len, 0);
- }
- #if defined(CONFIG_MACH_VIENNAATT)
- void tcon_interanl_clock(void)
- {
- /* ATT needs 577Mbps internal clock */
- char data[3];
- data[0] = 0x03; data[1] = 0xBB; data[2] = 0x27;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x2A; data[2] = 0x34;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x2B; data[2] = 0x6D;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x32; data[2] = 0x34;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x33; data[2] = 0x6D;
- aux_tx(0x491, data, 3);
- }
- #elif defined(CONFIG_MACH_PICASSO_SPR)
- void tcon_interanl_clock(void)
- {
- /* SPR needs 900Mbps internal clock */
- char data[3];
- //900Mbps
- data[0] = 0x03; data[1] = 0xBB; data[2] = 0x26;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x2A; data[2] = 0x28;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x2B; data[2] = 0x43;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x2E; data[2] = 0x28;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x2F; data[2] = 0x43;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x32; data[2] = 0x28;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x33; data[2] = 0x43;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x36; data[2] = 0x28;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x37; data[2] = 0x43;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x46; data[2] = 0x28;
- aux_tx(0x491, data, 3);
- data[0] = 0x05; data[1] = 0x47; data[2] = 0x43;
- aux_tx(0x491, data, 3);
- }
- #else
- void tcon_interanl_clock(void)
- {
- pr_debug("%s not change tcon internal clock", __func__);
- }
- #endif
- void read_firmware_version(char *string)
- {
- struct mdss_edp_drv_pdata *ep = get_global_ep();
- char *bp;
- struct edp_buf *rp;
- unsigned char data[4];
- int read_size = 8;
- if (!ep) {
- pr_info("%s error", __func__);
- return ;
- }
- rp = &ep->rxp;
- bp = rp->data;
- /* Indirect mode read eeprom*/
- data[0] = 0x51;
- data[1] = 0x0F; //MSB ADDR
- data[2] = 0xEC; //LSB ADDR
- data[3] = 0xC1;
- edp_aux_write_buf(ep, 0x45C, data, 4, 0);
- usleep(1000);
- edp_aux_read_buf(ep, 0x454, read_size, 0);
- memcpy(string, bp, read_size);
- data[0] = 0x51;
- data[1] = 0x0F; //MSB ADDR
- data[2] = 0xF4; //LSB ADDR
- data[3] = 0xC1;
- edp_aux_write_buf(ep, 0x45C, data, 4, 0);
- usleep(1000);
- edp_aux_read_buf(ep, 0x454, read_size, 0);
- memcpy(string + read_size, bp, read_size);
- string[16] = '\0';
- }
- #endif
- void mdss_edp_aux_init(struct mdss_edp_drv_pdata *ep)
- {
- mutex_init(&ep->aux_mutex);
- mutex_init(&ep->train_mutex);
- init_completion(&ep->aux_comp);
- init_completion(&ep->train_comp);
- init_completion(&ep->idle_comp);
- init_completion(&ep->video_comp);
- complete(&ep->train_comp); /* make non block at first time */
- complete(&ep->video_comp); /* make non block at first time */
- edp_buf_init(&ep->txp, ep->txbuf, sizeof(ep->txbuf));
- edp_buf_init(&ep->rxp, ep->rxbuf, sizeof(ep->rxbuf));
- }
|