mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm_fb: display: add dcs command list for dsi command mode
DSI dcs commands and mdp pixel stream share same dsi link. Add dcs command list to serialize sending dcs command and mdp pixel stream to avoid contention which may cause dsi controller to stall. Change-Id: Ie0e687f45be479d2137eb7b56b8d32040fba2044 Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org> Conflicts: drivers/video/msm/mdp4.h Signed-off-by: Naseer Ahmed <naseer@codeaurora.org>
This commit is contained in:
parent
5947f6f74c
commit
5e6d6c1c23
5 changed files with 356 additions and 199 deletions
|
@ -554,6 +554,7 @@ void mdp4_overlay0_done_dsi_video(int cndx);
|
|||
void mdp4_overlay0_done_dsi_cmd(int cndx);
|
||||
void mdp4_primary_rdptr(void);
|
||||
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
|
||||
int mdp4_overlay_commit(struct fb_info *info, int mixer);
|
||||
int mdp4_dsi_video_pipe_commit(int cndx, int wait);
|
||||
int mdp4_dsi_cmd_pipe_commit(int cndx, int wait);
|
||||
int mdp4_lcdc_pipe_commit(int cndx, int wait);
|
||||
|
@ -854,9 +855,6 @@ void mdp4_dsi_cmd_3d_sbys(struct msm_fb_data_type *mfd,
|
|||
void mdp4_dsi_video_3d_sbys(struct msm_fb_data_type *mfd,
|
||||
struct msmfb_overlay_3d *r3d);
|
||||
|
||||
void mdp4_backlight_init(int cndx);
|
||||
void mdp4_backlight_put_level(int cndx, int level);
|
||||
|
||||
int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info);
|
||||
|
||||
void mdp_dmap_vsync_set(int enable);
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
#include "mdp.h"
|
||||
#include "msm_fb.h"
|
||||
#include "mdp4.h"
|
||||
#include "mipi_dsi.h"
|
||||
#include "mdp4.h"
|
||||
|
||||
static int dsi_state;
|
||||
|
||||
|
@ -40,14 +40,6 @@ static int vsync_start_y_adjust = 4;
|
|||
|
||||
#define MAX_CONTROLLER 1
|
||||
#define VSYNC_EXPIRE_TICK 4
|
||||
#define BACKLIGHT_MAX 4
|
||||
|
||||
struct backlight {
|
||||
int put;
|
||||
int get;
|
||||
int tot;
|
||||
int blist[BACKLIGHT_MAX];
|
||||
};
|
||||
|
||||
static struct vsycn_ctrl {
|
||||
struct device *dev;
|
||||
|
@ -75,7 +67,6 @@ static struct vsycn_ctrl {
|
|||
struct msm_fb_data_type *mfd;
|
||||
struct mdp4_overlay_pipe *base_pipe;
|
||||
struct vsync_update vlist[2];
|
||||
struct backlight blight;
|
||||
int vsync_enabled;
|
||||
int clk_enabled;
|
||||
int clk_control;
|
||||
|
@ -108,68 +99,6 @@ static void vsync_irq_disable(int intr, int term)
|
|||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
}
|
||||
|
||||
static int mdp4_backlight_get_level(struct vsycn_ctrl *vctrl)
|
||||
{
|
||||
int level = -1;
|
||||
|
||||
mutex_lock(&vctrl->update_lock);
|
||||
if (vctrl->blight.tot) {
|
||||
level = vctrl->blight.blist[vctrl->blight.get];
|
||||
vctrl->blight.get++;
|
||||
vctrl->blight.get %= BACKLIGHT_MAX;
|
||||
vctrl->blight.tot--;
|
||||
pr_debug("%s: tot=%d put=%d get=%d level=%d\n", __func__,
|
||||
vctrl->blight.tot, vctrl->blight.put, vctrl->blight.get, level);
|
||||
}
|
||||
mutex_unlock(&vctrl->update_lock);
|
||||
return level;
|
||||
}
|
||||
|
||||
void mdp4_backlight_put_level(int cndx, int level)
|
||||
{
|
||||
struct vsycn_ctrl *vctrl;
|
||||
|
||||
if (cndx >= MAX_CONTROLLER) {
|
||||
pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
|
||||
return;
|
||||
}
|
||||
|
||||
vctrl = &vsync_ctrl_db[cndx];
|
||||
mutex_lock(&vctrl->update_lock);
|
||||
vctrl->blight.blist[vctrl->blight.put] = level;
|
||||
vctrl->blight.put++;
|
||||
vctrl->blight.put %= BACKLIGHT_MAX;
|
||||
if (vctrl->blight.tot == BACKLIGHT_MAX) {
|
||||
/* drop the oldest one */
|
||||
vctrl->blight.get++;
|
||||
vctrl->blight.get %= BACKLIGHT_MAX;
|
||||
} else {
|
||||
vctrl->blight.tot++;
|
||||
}
|
||||
mutex_unlock(&vctrl->update_lock);
|
||||
pr_debug("%s: tot=%d put=%d get=%d level=%d\n", __func__,
|
||||
vctrl->blight.tot, vctrl->blight.put, vctrl->blight.get, level);
|
||||
|
||||
if (mdp4_overlay_dsi_state_get() <= ST_DSI_SUSPEND)
|
||||
return;
|
||||
}
|
||||
|
||||
static int mdp4_backlight_commit_level(struct vsycn_ctrl *vctrl)
|
||||
{
|
||||
int level;
|
||||
int cnt = 0;
|
||||
|
||||
if (vctrl->blight.tot) { /* has new backlight */
|
||||
if (mipi_dsi_ctrl_lock(0)) {
|
||||
level = mdp4_backlight_get_level(vctrl);
|
||||
mipi_dsi_cmd_backlight_tx(level);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe)
|
||||
{
|
||||
uint32 off, addr;
|
||||
|
@ -356,9 +285,6 @@ int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
|
|||
}
|
||||
mutex_unlock(&vctrl->update_lock);
|
||||
|
||||
|
||||
mdp4_backlight_commit_level(vctrl);
|
||||
|
||||
/* free previous committed iommu back to pool */
|
||||
mdp4_overlay_iommu_unmap_freelist(mixer);
|
||||
|
||||
|
@ -425,6 +351,9 @@ int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
|
|||
}
|
||||
}
|
||||
|
||||
/* tx dcs command if had any */
|
||||
mipi_dsi_cmdlist_commit(1);
|
||||
|
||||
mdp4_mixer_stage_commit(mixer);
|
||||
|
||||
pipe = vctrl->base_pipe;
|
||||
|
@ -698,9 +627,6 @@ void mdp4_dsi_rdptr_init(int cndx)
|
|||
|
||||
vctrl->inited = 1;
|
||||
vctrl->update_ndx = 0;
|
||||
vctrl->blight.put = 0;
|
||||
vctrl->blight.get = 0;
|
||||
vctrl->blight.tot = 0;
|
||||
mutex_init(&vctrl->update_lock);
|
||||
init_completion(&vctrl->ov_comp);
|
||||
init_completion(&vctrl->dmap_comp);
|
||||
|
@ -1040,8 +966,6 @@ int mdp4_dsi_cmd_off(struct platform_device *pdev)
|
|||
|
||||
atomic_set(&vctrl->suspend, 1);
|
||||
|
||||
mipi_dsi_cmd_backlight_tx(150);
|
||||
|
||||
/* sanity check, free pipes besides base layer */
|
||||
mdp4_overlay_unset_mixer(pipe->mixer_num);
|
||||
mdp4_mixer_stage_down(pipe, 1);
|
||||
|
|
|
@ -117,6 +117,9 @@ enum dsi_trigger_type {
|
|||
#define DSI_INTR_CMD_DMA_DONE_MASK BIT(1)
|
||||
#define DSI_INTR_CMD_DMA_DONE BIT(0)
|
||||
|
||||
#define DSI_MDP_TERM BIT(8)
|
||||
#define DSI_CMD_TERM BIT(0)
|
||||
|
||||
#define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */
|
||||
#define DSI_CMD_TRIGGER_TE 0x02
|
||||
#define DSI_CMD_TRIGGER_SW 0x04
|
||||
|
@ -185,8 +188,8 @@ struct dsi_clk_desc {
|
|||
#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
|
||||
#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
|
||||
|
||||
#define DSI_BUF_SIZE 1024
|
||||
#define MIPI_DSI_MRPS 0x04 /* Maximum Return Packet Size */
|
||||
#define DSI_BUF_SIZE 64
|
||||
#define MIPI_DSI_MRPS 0x04 /* Maximum Return Packet Size */
|
||||
|
||||
#define MIPI_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
|
||||
|
||||
|
@ -247,7 +250,6 @@ struct dsi_cmd_desc {
|
|||
char *payload;
|
||||
};
|
||||
|
||||
|
||||
typedef void (*kickoff_act)(void *);
|
||||
|
||||
struct dsi_kickoff_action {
|
||||
|
@ -257,6 +259,30 @@ struct dsi_kickoff_action {
|
|||
};
|
||||
|
||||
|
||||
#define CMD_REQ_MAX 4
|
||||
|
||||
typedef void (*fxn)(u32 data);
|
||||
|
||||
#define CMD_REQ_RX 0x0001
|
||||
#define CMD_REQ_COMMIT 0x0002
|
||||
#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
|
||||
|
||||
struct dcs_cmd_req {
|
||||
struct dsi_cmd_desc *cmds;
|
||||
int cmds_cnt;
|
||||
u32 flags;
|
||||
int rlen; /* rx length */
|
||||
fxn cb;
|
||||
};
|
||||
|
||||
struct dcs_cmd_list {
|
||||
int put;
|
||||
int get;
|
||||
int tot;
|
||||
struct dcs_cmd_req list[CMD_REQ_MAX];
|
||||
};
|
||||
|
||||
|
||||
char *mipi_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
|
||||
char *mipi_dsi_buf_init(struct dsi_buf *dp);
|
||||
void mipi_dsi_init(void);
|
||||
|
@ -284,7 +310,7 @@ void mipi_dsi_ack_err_status(void);
|
|||
void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd);
|
||||
void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd);
|
||||
void mipi_dsi_set_backlight(struct msm_fb_data_type *mfd, int level);
|
||||
void mipi_dsi_cmd_backlight_tx(int level);
|
||||
void mipi_dsi_cmd_backlight_tx(struct dsi_buf *dp);
|
||||
void mipi_dsi_clk_enable(void);
|
||||
void mipi_dsi_clk_disable(void);
|
||||
void mipi_dsi_pre_kickoff_action(void);
|
||||
|
@ -315,6 +341,10 @@ void mipi_dsi_turn_on_clks(void);
|
|||
void mipi_dsi_turn_off_clks(void);
|
||||
void mipi_dsi_clk_cfg(int on);
|
||||
|
||||
int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq);
|
||||
struct dcs_cmd_req *mipi_dsi_cmdlist_get(void);
|
||||
void mipi_dsi_cmdlist_commit(int from_mdp);
|
||||
|
||||
#ifdef CONFIG_FB_MSM_MDP303
|
||||
void update_lane_config(struct msm_panel_info *pinfo);
|
||||
#endif
|
||||
|
|
|
@ -43,12 +43,13 @@
|
|||
static struct completion dsi_dma_comp;
|
||||
static struct completion dsi_mdp_comp;
|
||||
static struct dsi_buf dsi_tx_buf;
|
||||
static int dsi_irq_enabled;
|
||||
static struct dsi_buf dsi_rx_buf;
|
||||
static spinlock_t dsi_irq_lock;
|
||||
static spinlock_t dsi_mdp_lock;
|
||||
spinlock_t dsi_clk_lock;
|
||||
static int dsi_ctrl_lock;
|
||||
static int dsi_mdp_busy;
|
||||
static struct mutex cmd_mutex;
|
||||
|
||||
static struct list_head pre_kickoff_list;
|
||||
static struct list_head post_kickoff_list;
|
||||
|
@ -60,6 +61,8 @@ enum {
|
|||
STAT_DSI_MDP
|
||||
};
|
||||
|
||||
struct dcs_cmd_list cmdlist;
|
||||
|
||||
#ifdef CONFIG_FB_MSM_MDP40
|
||||
void mipi_dsi_mdp_stat_inc(int which)
|
||||
{
|
||||
|
@ -91,42 +94,52 @@ void mipi_dsi_init(void)
|
|||
init_completion(&dsi_dma_comp);
|
||||
init_completion(&dsi_mdp_comp);
|
||||
mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
|
||||
mipi_dsi_buf_alloc(&dsi_rx_buf, DSI_BUF_SIZE);
|
||||
spin_lock_init(&dsi_irq_lock);
|
||||
spin_lock_init(&dsi_mdp_lock);
|
||||
spin_lock_init(&dsi_clk_lock);
|
||||
mutex_init(&cmd_mutex);
|
||||
|
||||
INIT_LIST_HEAD(&pre_kickoff_list);
|
||||
INIT_LIST_HEAD(&post_kickoff_list);
|
||||
}
|
||||
|
||||
void mipi_dsi_enable_irq(void)
|
||||
|
||||
static u32 dsi_irq_mask;
|
||||
|
||||
void mipi_dsi_enable_irq(u32 term)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dsi_irq_lock, flags);
|
||||
if (dsi_irq_enabled) {
|
||||
pr_debug("%s: IRQ aleady enabled\n", __func__);
|
||||
if (dsi_irq_mask & term) {
|
||||
spin_unlock_irqrestore(&dsi_irq_lock, flags);
|
||||
return;
|
||||
}
|
||||
dsi_irq_enabled = 1;
|
||||
enable_irq(dsi_irq);
|
||||
if (dsi_irq_mask == 0) {
|
||||
enable_irq(dsi_irq);
|
||||
pr_debug("%s: IRQ Enable, mask=%x term=%x\n",
|
||||
__func__, (int)dsi_irq_mask, (int)term);
|
||||
}
|
||||
dsi_irq_mask |= term;
|
||||
spin_unlock_irqrestore(&dsi_irq_lock, flags);
|
||||
}
|
||||
|
||||
void mipi_dsi_disable_irq(void)
|
||||
void mipi_dsi_disable_irq(u32 term)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dsi_irq_lock, flags);
|
||||
if (dsi_irq_enabled == 0) {
|
||||
pr_debug("%s: IRQ already disabled\n", __func__);
|
||||
if (!(dsi_irq_mask & term)) {
|
||||
spin_unlock_irqrestore(&dsi_irq_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dsi_irq_enabled = 0;
|
||||
disable_irq(dsi_irq);
|
||||
dsi_irq_mask &= ~term;
|
||||
if (dsi_irq_mask == 0) {
|
||||
disable_irq(dsi_irq);
|
||||
pr_debug("%s: IRQ Disable, mask=%x term=%x\n",
|
||||
__func__, (int)dsi_irq_mask, (int)term);
|
||||
}
|
||||
spin_unlock_irqrestore(&dsi_irq_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -134,17 +147,19 @@ void mipi_dsi_disable_irq(void)
|
|||
* mipi_dsi_disale_irq_nosync() should be called
|
||||
* from interrupt context
|
||||
*/
|
||||
void mipi_dsi_disable_irq_nosync(void)
|
||||
void mipi_dsi_disable_irq_nosync(u32 term)
|
||||
{
|
||||
spin_lock(&dsi_irq_lock);
|
||||
if (dsi_irq_enabled == 0) {
|
||||
pr_debug("%s: IRQ cannot be disabled\n", __func__);
|
||||
if (!(dsi_irq_mask & term)) {
|
||||
spin_unlock(&dsi_irq_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
dsi_irq_enabled = 0;
|
||||
disable_irq_nosync(dsi_irq);
|
||||
dsi_irq_mask &= ~term;
|
||||
if (dsi_irq_mask == 0) {
|
||||
disable_irq_nosync(dsi_irq);
|
||||
pr_debug("%s: IRQ Disable, mask=%x term=%x\n",
|
||||
__func__, (int)dsi_irq_mask, (int)term);
|
||||
}
|
||||
spin_unlock(&dsi_irq_lock);
|
||||
}
|
||||
|
||||
|
@ -1007,27 +1022,6 @@ void mipi_dsi_op_mode_config(int mode)
|
|||
wmb();
|
||||
}
|
||||
|
||||
int mipi_dsi_ctrl_lock(int mdp)
|
||||
{
|
||||
unsigned long flag;
|
||||
int lock = 0;
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flag);
|
||||
if (dsi_ctrl_lock == FALSE) {
|
||||
dsi_ctrl_lock = TRUE;
|
||||
lock = 1;
|
||||
if (lock && mdp) /* mdp pixel */
|
||||
mipi_dsi_enable_irq();
|
||||
}
|
||||
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
|
||||
return lock;
|
||||
}
|
||||
|
||||
int mipi_dsi_ctrl_lock_query()
|
||||
{
|
||||
return dsi_ctrl_lock;
|
||||
}
|
||||
|
||||
void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
unsigned long flag;
|
||||
|
@ -1063,7 +1057,7 @@ void mipi_dsi_cmd_mdp_start(void)
|
|||
mipi_dsi_mdp_stat_inc(STAT_DSI_START);
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flag);
|
||||
mipi_dsi_enable_irq();
|
||||
mipi_dsi_enable_irq(DSI_MDP_TERM);
|
||||
dsi_mdp_busy = TRUE;
|
||||
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
|
||||
}
|
||||
|
@ -1137,51 +1131,6 @@ int mipi_dsi_cmd_reg_tx(uint32 data)
|
|||
return 4;
|
||||
}
|
||||
|
||||
static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
|
||||
|
||||
static struct dsi_cmd_desc backlight_cmd = {
|
||||
DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
|
||||
|
||||
/*
|
||||
* mipi_dsi_cmd_backlight_tx:
|
||||
* thread context only
|
||||
*/
|
||||
void mipi_dsi_cmd_backlight_tx(int level)
|
||||
{
|
||||
struct dsi_buf *tp;
|
||||
struct dsi_cmd_desc *cmd;
|
||||
unsigned long flag;
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flag);
|
||||
dsi_mdp_busy = TRUE;
|
||||
led_pwm1[1] = (unsigned char)(level);
|
||||
tp = &dsi_tx_buf;
|
||||
cmd = &backlight_cmd;
|
||||
mipi_dsi_buf_init(&dsi_tx_buf);
|
||||
|
||||
if (tp->dmap) {
|
||||
dma_unmap_single(&dsi_dev, tp->dmap, tp->len, DMA_TO_DEVICE);
|
||||
tp->dmap = 0;
|
||||
}
|
||||
|
||||
mipi_dsi_enable_irq();
|
||||
mipi_dsi_cmd_dma_add(tp, cmd);
|
||||
|
||||
tp->len += 3;
|
||||
tp->len &= ~0x03; /* multipled by 4 */
|
||||
|
||||
tp->dmap = dma_map_single(&dsi_dev, tp->data, tp->len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(&dsi_dev, tp->dmap))
|
||||
pr_err("%s: dmap mapp failed\n", __func__);
|
||||
|
||||
MIPI_OUTP(MIPI_DSI_BASE + 0x044, tp->dmap);
|
||||
MIPI_OUTP(MIPI_DSI_BASE + 0x048, tp->len);
|
||||
wmb();
|
||||
MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
|
||||
wmb();
|
||||
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* mipi_dsi_cmds_tx:
|
||||
* thread context only
|
||||
|
@ -1212,7 +1161,7 @@ int mipi_dsi_cmds_tx(struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
|
|||
cm = cmds;
|
||||
mipi_dsi_buf_init(tp);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
mipi_dsi_enable_irq();
|
||||
mipi_dsi_enable_irq(DSI_CMD_TERM);
|
||||
mipi_dsi_buf_init(tp);
|
||||
mipi_dsi_cmd_dma_add(tp, cm);
|
||||
mipi_dsi_cmd_dma_tx(tp);
|
||||
|
@ -1303,20 +1252,20 @@ int mipi_dsi_cmds_rx(struct msm_fb_data_type *mfd,
|
|||
/* packet size need to be set at every read */
|
||||
pkt_size = len;
|
||||
max_pktsize[0] = pkt_size;
|
||||
mipi_dsi_enable_irq();
|
||||
mipi_dsi_enable_irq(DSI_CMD_TERM);
|
||||
mipi_dsi_buf_init(tp);
|
||||
mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
|
||||
mipi_dsi_cmd_dma_tx(tp);
|
||||
}
|
||||
|
||||
mipi_dsi_enable_irq();
|
||||
mipi_dsi_enable_irq(DSI_CMD_TERM);
|
||||
mipi_dsi_buf_init(tp);
|
||||
mipi_dsi_cmd_dma_add(tp, cmds);
|
||||
|
||||
/* transmit read comamnd to client */
|
||||
mipi_dsi_cmd_dma_tx(tp);
|
||||
|
||||
mipi_dsi_disable_irq();
|
||||
mipi_dsi_disable_irq(DSI_CMD_TERM);
|
||||
/*
|
||||
* once cmd_dma_done interrupt received,
|
||||
* return data from client is ready and stored
|
||||
|
@ -1375,6 +1324,126 @@ int mipi_dsi_cmds_rx(struct msm_fb_data_type *mfd,
|
|||
return rp->len;
|
||||
}
|
||||
|
||||
int mipi_dsi_cmds_rx_new(struct dsi_buf *tp, struct dsi_buf *rp,
|
||||
struct dcs_cmd_req *req, int rlen)
|
||||
{
|
||||
struct dsi_cmd_desc *cmds;
|
||||
int cnt, len, diff, pkt_size;
|
||||
char cmd;
|
||||
unsigned long flag;
|
||||
|
||||
if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
|
||||
/* Only support rlen = 4*n */
|
||||
rlen += 3;
|
||||
rlen &= ~0x03;
|
||||
}
|
||||
|
||||
cmds = req->cmds;
|
||||
|
||||
len = rlen;
|
||||
diff = 0;
|
||||
|
||||
if (len <= 2)
|
||||
cnt = 4; /* short read */
|
||||
else {
|
||||
if (len > MIPI_DSI_LEN)
|
||||
len = MIPI_DSI_LEN; /* 8 bytes at most */
|
||||
|
||||
len = (len + 3) & ~0x03; /* len 4 bytes align */
|
||||
diff = len - rlen;
|
||||
/*
|
||||
* add extra 2 bytes to len to have overall
|
||||
* packet size is multipe by 4. This also make
|
||||
* sure 4 bytes dcs headerlocates within a
|
||||
* 32 bits register after shift in.
|
||||
* after all, len should be either 6 or 10.
|
||||
*/
|
||||
len += 2;
|
||||
cnt = len + 6; /* 4 bytes header + 2 bytes crc */
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flag);
|
||||
dsi_mdp_busy = TRUE;
|
||||
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
|
||||
|
||||
if (!(req->flags & CMD_REQ_NO_MAX_PKT_SIZE)) {
|
||||
|
||||
|
||||
/* packet size need to be set at every read */
|
||||
pkt_size = len;
|
||||
max_pktsize[0] = pkt_size;
|
||||
mipi_dsi_enable_irq(DSI_CMD_TERM);
|
||||
mipi_dsi_buf_init(tp);
|
||||
mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
|
||||
mipi_dsi_cmd_dma_tx(tp);
|
||||
}
|
||||
|
||||
mipi_dsi_enable_irq(DSI_CMD_TERM);
|
||||
mipi_dsi_buf_init(tp);
|
||||
mipi_dsi_cmd_dma_add(tp, cmds);
|
||||
|
||||
/* transmit read comamnd to client */
|
||||
mipi_dsi_cmd_dma_tx(tp);
|
||||
|
||||
mipi_dsi_disable_irq(DSI_CMD_TERM);
|
||||
/*
|
||||
* once cmd_dma_done interrupt received,
|
||||
* return data from client is ready and stored
|
||||
* at RDBK_DATA register already
|
||||
*/
|
||||
mipi_dsi_buf_init(rp);
|
||||
if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
|
||||
/*
|
||||
* expect rlen = n * 4
|
||||
* short alignement for start addr
|
||||
*/
|
||||
rp->data += 2;
|
||||
}
|
||||
|
||||
mipi_dsi_cmd_dma_rx(rp, cnt);
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flag);
|
||||
dsi_mdp_busy = FALSE;
|
||||
complete(&dsi_mdp_comp);
|
||||
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
|
||||
|
||||
if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
|
||||
/*
|
||||
* remove extra 2 bytes from previous
|
||||
* rx transaction at shift register
|
||||
* which was inserted during copy
|
||||
* shift registers to rx buffer
|
||||
* rx payload start from long alignment addr
|
||||
*/
|
||||
rp->data += 2;
|
||||
}
|
||||
|
||||
cmd = rp->data[0];
|
||||
switch (cmd) {
|
||||
case DTYPE_ACK_ERR_RESP:
|
||||
pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
|
||||
break;
|
||||
case DTYPE_GEN_READ1_RESP:
|
||||
case DTYPE_DCS_READ1_RESP:
|
||||
mipi_dsi_short_read1_resp(rp);
|
||||
break;
|
||||
case DTYPE_GEN_READ2_RESP:
|
||||
case DTYPE_DCS_READ2_RESP:
|
||||
mipi_dsi_short_read2_resp(rp);
|
||||
break;
|
||||
case DTYPE_GEN_LREAD_RESP:
|
||||
case DTYPE_DCS_LREAD_RESP:
|
||||
mipi_dsi_long_read_resp(rp);
|
||||
rp->len -= 2; /* extra 2 bytes added */
|
||||
rp->len -= diff; /* align bytes */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rp->len;
|
||||
}
|
||||
|
||||
int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -1392,6 +1461,11 @@ int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
|
|||
pr_debug("\n");
|
||||
#endif
|
||||
|
||||
if (tp->len == 0) {
|
||||
pr_err("%s: Error, len=0\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flags);
|
||||
tp->len += 3;
|
||||
tp->len &= ~0x03; /* multipled by 4 */
|
||||
|
@ -1446,6 +1520,134 @@ int mipi_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
|
|||
return rlen;
|
||||
}
|
||||
|
||||
void mipi_dsi_cmd_mdp_busy(void)
|
||||
{
|
||||
u32 status;
|
||||
unsigned long flags;
|
||||
int need_wait;
|
||||
|
||||
spin_lock_irqsave(&dsi_mdp_lock, flags);
|
||||
status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
|
||||
if (status & 0x04) { /* MDP BUSY */
|
||||
INIT_COMPLETION(dsi_mdp_comp);
|
||||
need_wait = 1;
|
||||
pr_debug("%s: status=%x need_wait\n", __func__, (int)status);
|
||||
mipi_dsi_enable_irq(DSI_MDP_TERM);
|
||||
}
|
||||
spin_unlock_irqrestore(&dsi_mdp_lock, flags);
|
||||
|
||||
if (need_wait)
|
||||
wait_for_completion(&dsi_mdp_comp);
|
||||
}
|
||||
|
||||
/*
|
||||
* mipi_dsi_cmd_get: cmd_mutex acquired by caller
|
||||
*/
|
||||
struct dcs_cmd_req *mipi_dsi_cmdlist_get(void)
|
||||
{
|
||||
struct dcs_cmd_req *req = NULL;
|
||||
|
||||
if (cmdlist.get != cmdlist.put) {
|
||||
req = &cmdlist.list[cmdlist.get];
|
||||
cmdlist.get++;
|
||||
cmdlist.get %= CMD_REQ_MAX;
|
||||
cmdlist.tot--;
|
||||
pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
|
||||
cmdlist.tot, cmdlist.put, cmdlist.get);
|
||||
}
|
||||
return req;
|
||||
}
|
||||
void mipi_dsi_cmdlist_tx(struct dcs_cmd_req *req)
|
||||
{
|
||||
struct dsi_buf *tp;
|
||||
int ret;
|
||||
|
||||
mipi_dsi_buf_init(&dsi_tx_buf);
|
||||
tp = &dsi_tx_buf;
|
||||
ret = mipi_dsi_cmds_tx(tp, req->cmds, req->cmds_cnt);
|
||||
|
||||
if (req->cb)
|
||||
req->cb(ret);
|
||||
|
||||
}
|
||||
|
||||
void mipi_dsi_cmdlist_rx(struct dcs_cmd_req *req)
|
||||
{
|
||||
int len;
|
||||
u32 *dp;
|
||||
struct dsi_buf *tp;
|
||||
struct dsi_buf *rp;
|
||||
|
||||
mipi_dsi_buf_init(&dsi_tx_buf);
|
||||
mipi_dsi_buf_init(&dsi_rx_buf);
|
||||
|
||||
tp = &dsi_tx_buf;
|
||||
rp = &dsi_rx_buf;
|
||||
|
||||
len = mipi_dsi_cmds_rx_new(tp, rp, req, req->rlen);
|
||||
dp = (u32 *)rp->data;
|
||||
|
||||
if (req->cb)
|
||||
req->cb(*dp);
|
||||
}
|
||||
|
||||
void mipi_dsi_cmdlist_commit(int from_mdp)
|
||||
{
|
||||
struct dcs_cmd_req *req;
|
||||
|
||||
mutex_lock(&cmd_mutex);
|
||||
req = mipi_dsi_cmdlist_get();
|
||||
if (req == NULL) {
|
||||
mutex_unlock(&cmd_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
|
||||
|
||||
if (!from_mdp) { /* from put */
|
||||
/* make sure dsi_cmd_mdp is idle */
|
||||
mipi_dsi_cmd_mdp_busy();
|
||||
}
|
||||
|
||||
if (req->flags && CMD_REQ_RX)
|
||||
mipi_dsi_cmdlist_rx(req);
|
||||
else
|
||||
mipi_dsi_cmdlist_tx(req);
|
||||
|
||||
mutex_unlock(&cmd_mutex);
|
||||
}
|
||||
|
||||
int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq)
|
||||
{
|
||||
struct dcs_cmd_req *req;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&cmd_mutex);
|
||||
req = &cmdlist.list[cmdlist.put];
|
||||
*req = *cmdreq;
|
||||
cmdlist.put++;
|
||||
cmdlist.put %= CMD_REQ_MAX;
|
||||
cmdlist.tot++;
|
||||
if (cmdlist.put == cmdlist.get) {
|
||||
/* drop the oldest one */
|
||||
pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
|
||||
cmdlist.tot, cmdlist.put, cmdlist.get);
|
||||
cmdlist.get++;
|
||||
cmdlist.get %= CMD_REQ_MAX;
|
||||
cmdlist.tot--;
|
||||
}
|
||||
mutex_unlock(&cmd_mutex);
|
||||
|
||||
ret++;
|
||||
pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
|
||||
cmdlist.tot, cmdlist.put, cmdlist.get);
|
||||
|
||||
if (req->flags & CMD_REQ_COMMIT)
|
||||
mipi_dsi_cmdlist_commit(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mipi_dsi_irq_set(uint32 mask, uint32 irq)
|
||||
{
|
||||
uint32 data;
|
||||
|
@ -1534,6 +1736,8 @@ irqreturn_t mipi_dsi_isr(int irq, void *ptr)
|
|||
isr = MIPI_INP(MIPI_DSI_BASE + 0x010c);/* DSI_INTR_CTRL */
|
||||
MIPI_OUTP(MIPI_DSI_BASE + 0x010c, isr);
|
||||
|
||||
pr_debug("%s: isr=%x\n", __func__, (int)isr);
|
||||
|
||||
#ifdef CONFIG_FB_MSM_MDP40
|
||||
mdp4_stat.intr_dsi++;
|
||||
#endif
|
||||
|
@ -1553,7 +1757,7 @@ irqreturn_t mipi_dsi_isr(int irq, void *ptr)
|
|||
spin_lock(&dsi_mdp_lock);
|
||||
complete(&dsi_dma_comp);
|
||||
dsi_ctrl_lock = FALSE;
|
||||
mipi_dsi_disable_irq_nosync();
|
||||
mipi_dsi_disable_irq_nosync(DSI_CMD_TERM);
|
||||
spin_unlock(&dsi_mdp_lock);
|
||||
}
|
||||
|
||||
|
@ -1561,7 +1765,7 @@ irqreturn_t mipi_dsi_isr(int irq, void *ptr)
|
|||
mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
|
||||
spin_lock(&dsi_mdp_lock);
|
||||
dsi_ctrl_lock = FALSE;
|
||||
mipi_dsi_disable_irq_nosync();
|
||||
mipi_dsi_disable_irq_nosync(DSI_MDP_TERM);
|
||||
dsi_mdp_busy = FALSE;
|
||||
complete(&dsi_mdp_comp);
|
||||
spin_unlock(&dsi_mdp_lock);
|
||||
|
|
|
@ -393,18 +393,16 @@ static int mipi_novatek_lcd_on(struct platform_device *pdev)
|
|||
|
||||
mipi = &mfd->panel_info.mipi;
|
||||
|
||||
if (mipi_dsi_ctrl_lock(0)) {
|
||||
if (mipi->mode == DSI_VIDEO_MODE) {
|
||||
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_video_on_cmds,
|
||||
if (mipi->mode == DSI_VIDEO_MODE) {
|
||||
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_video_on_cmds,
|
||||
ARRAY_SIZE(novatek_video_on_cmds));
|
||||
} else {
|
||||
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
|
||||
} else {
|
||||
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
|
||||
ARRAY_SIZE(novatek_cmd_on_cmds));
|
||||
|
||||
/* clean up ack_err_status */
|
||||
mipi_dsi_cmd_bta_sw_trigger();
|
||||
mipi_novatek_manufacture_id(mfd);
|
||||
}
|
||||
/* clean up ack_err_status */
|
||||
mipi_dsi_cmd_bta_sw_trigger();
|
||||
mipi_novatek_manufacture_id(mfd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -421,35 +419,38 @@ static int mipi_novatek_lcd_off(struct platform_device *pdev)
|
|||
if (mfd->key != MFD_KEY)
|
||||
return -EINVAL;
|
||||
|
||||
if (mipi_dsi_ctrl_lock(0)) {
|
||||
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_display_off_cmds,
|
||||
mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_display_off_cmds,
|
||||
ARRAY_SIZE(novatek_display_off_cmds));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_LED_TRIGGER(bkl_led_trigger);
|
||||
|
||||
#ifdef CONFIG_FB_MSM_MDP303
|
||||
void mdp4_backlight_put_level(int cndx, int level)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
#endif
|
||||
static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
|
||||
static struct dsi_cmd_desc backlight_cmd = {
|
||||
DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
|
||||
|
||||
struct dcs_cmd_req cmdreq;
|
||||
|
||||
static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
struct mipi_panel_info *mipi;
|
||||
|
||||
if ((mipi_novatek_pdata->enable_wled_bl_ctrl)
|
||||
&& (wled_trigger_initialized)) {
|
||||
led_trigger_event(bkl_led_trigger, mfd->bl_level);
|
||||
return;
|
||||
}
|
||||
mipi = &mfd->panel_info.mipi;
|
||||
|
||||
mdp4_backlight_put_level(0, mfd->bl_level);
|
||||
led_pwm1[1] = (unsigned char)mfd->bl_level;
|
||||
|
||||
cmdreq.cmds = &backlight_cmd;
|
||||
cmdreq.cmds_cnt = 1;
|
||||
cmdreq.flags = 0;
|
||||
cmdreq.rlen = 0;
|
||||
cmdreq.cb = NULL;
|
||||
|
||||
mipi_dsi_cmdlist_put(&cmdreq);
|
||||
}
|
||||
|
||||
static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev);
|
||||
|
|
Loading…
Reference in a new issue