diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 178 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_hwio.h | 27 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 9 |
3 files changed, 213 insertions, 1 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 5c5b03c672e9..74038e522b47 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -2148,6 +2148,177 @@ static inline int mdss_mdp_set_split_ctl(struct mdss_mdp_ctl *ctl, return 0; } +static int mdss_mdp_ctl_dsc_enable(int enable, + struct mdss_mdp_mixer *mixer, + struct mdss_panel_info *pinfo) +{ + struct mdss_mdp_ctl *ctl; + struct dsc_desc *dsc; + u32 data; + u32 *lp; + char *cp; + int i, bpp, lsb; + char __iomem *offset, *off; + + if (pinfo->compression_mode != COMPRESSION_DSC) + return -EINVAL; + + if (mixer->num != MDSS_MDP_INTF_LAYERMIXER0 && + mixer->num != MDSS_MDP_INTF_LAYERMIXER1) { + pr_err("Mixer=%d doesn't support DSC.\n", mixer->num); + return -EINVAL; + } + + if (enable == 0) { + mdss_mdp_pingpong_write(mixer->pingpong_base, + MDSS_MDP_REG_PP_DSC_MODE, 0); + return 0; + } + + ctl = mixer->ctl; + + /* dce0_sel->pp0, dce1_sel->pp1 */ + writel_relaxed(0x0, ctl->mdata->mdp_base + + MDSS_MDP_REG_DCE_SEL); + + /* dsc enable */ + mdss_mdp_pingpong_write(mixer->pingpong_base, + MDSS_MDP_REG_PP_DSC_MODE, 1); + + data = mdss_mdp_pingpong_read(mixer->pingpong_base, + MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP); + data |= BIT(18); /* endian flip */ + mdss_mdp_pingpong_write(mixer->pingpong_base, + MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP, data); + + offset = ctl->mdata->mdp_base; + if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0) + offset += MDSS_MDP_DSC_0_OFFSET; + else + offset += MDSS_MDP_DSC_1_OFFSET; + + dsc = &pinfo->dsc; + if (pinfo->type == MIPI_VIDEO_PANEL) + data = BIT(2); /* vieo mode */ + + if (dsc->data_path_model == DSC_PATH_MERGE_1P1D) + data |= (BIT(0) | BIT(1)); + else if (dsc->data_path_model == DSC_PATH_SPLIT_1P2D) + data |= BIT(0); + + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_COMMON_MODE); + + data = dsc->ich_reset_value | dsc->ich_reset_override; + data <<= 28; + data |= (dsc->initial_lines << 20); + data |= ((dsc->slice_last_group_size - 1) << 18); + /* bpp is 6.4 format, 4 LSBs bits are for fractional part */ + lsb = dsc->bpp % 4; + bpp = dsc->bpp / 4; + bpp *= 4; /* either 8 or 12 */ + bpp <<= 4; + bpp |= lsb; + data |= (bpp << 8); + data |= (dsc->block_pred_enable << 7); + data |= (dsc->line_buf_depth << 3); + data |= (dsc->enable_422 << 2); + data |= (dsc->convert_rgb << 1); + data |= dsc->input_10_bits; + + pr_debug("%d %d %d %d %d %d %d %d %d %d, data=%x\n", + dsc->ich_reset_value, dsc->ich_reset_override, + dsc->initial_lines , dsc->slice_last_group_size, + dsc->bpp, dsc->block_pred_enable, dsc->line_buf_depth, + dsc->enable_422, dsc->convert_rgb, dsc->input_10_bits, data); + + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_ENC); + + data = dsc->pic_width << 16; + data |= dsc->pic_height; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_PICTURE); + + data = dsc->slice_width << 16; + data |= dsc->slice_height; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_SLICE); + + data = dsc->chunk_size << 16; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_CHUNK_SIZE); + + pr_debug("pic_w=%d pic_h=%d, slice_h=%d slice_w=%d, chunk=%d\n", + dsc->pic_width, dsc->pic_height, + dsc->slice_width, dsc->slice_height, dsc->chunk_size); + + data = dsc->initial_dec_delay << 16; + data |= dsc->initial_xmit_delay; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_DELAY); + + data = dsc->initial_scale_value; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_SCALE_INITIAL); + + data = dsc->scale_decrement_interval; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_SCALE_DEC_INTERVAL); + + data = dsc->scale_increment_interval; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_SCALE_INC_INTERVAL); + + data = dsc->first_line_bpg_offset; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_FIRST_LINE_BPG_OFFSET); + + data = dsc->nfl_bpg_offset << 16; + data |= dsc->slice_bpg_offset; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_BPG_OFFSET); + + data = dsc->initial_offset << 16; + data |= dsc->final_offset; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_DSC_OFFSET); + + data = dsc->det_thresh_flatness << 10; + data |= dsc->max_qp_flatness << 5; + data |= dsc->min_qp_flatness; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_FLATNESS); + writel_relaxed(0x983, offset + MDSS_MDP_REG_DSC_FLATNESS); + + data = dsc->rc_model_size; /* rate_buffer_size */ + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_RC_MODEL_SIZE); + + data = dsc->tgt_offset_lo << 18; + data |= dsc->tgt_offset_hi << 14; + data |= dsc->quant_incr_limit1 << 9; + data |= dsc->quant_incr_limit0 << 4; + data |= dsc->edge_factor; + writel_relaxed(data, offset + MDSS_MDP_REG_DSC_RC); + + lp = dsc->buf_thresh; + off = offset + MDSS_MDP_REG_DSC_RC_BUF_THRESH; + for (i = 0; i < 14; i++) { + writel_relaxed(*lp++, off); + off += 4; + } + + cp = dsc->range_min_qp; + off = offset + MDSS_MDP_REG_DSC_RANGE_MIN_QP; + for (i = 0; i < 15; i++) { + writel_relaxed(*cp++, off); + off += 4; + } + + cp = dsc->range_max_qp; + off = offset + MDSS_MDP_REG_DSC_RANGE_MAX_QP; + for (i = 0; i < 15; i++) { + writel_relaxed(*cp++, off); + off += 4; + } + + cp = dsc->range_bpg_offset; + off = offset + MDSS_MDP_REG_DSC_RANGE_BPG_OFFSET; + for (i = 0; i < 15; i++) { + writel_relaxed(*cp++, off); + off += 4; + } + + return 0; +} + static int mdss_mdp_ctl_fbc_enable(int enable, struct mdss_mdp_mixer *mixer, struct mdss_panel_info *pdata) { @@ -2778,7 +2949,12 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff) outsize = (mixer->height << 16) | mixer->width; mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize); - if (ctl->panel_data->panel_info.fbc.enabled) { + if (ctl->panel_data->panel_info.compression_mode == + COMPRESSION_DSC) { + ret = mdss_mdp_ctl_dsc_enable(1, ctl->mixer_left, + &ctl->panel_data->panel_info); + } else if (ctl->panel_data->panel_info.compression_mode == + COMPRESSION_FBC) { ret = mdss_mdp_ctl_fbc_enable(1, ctl->mixer_left, &ctl->panel_data->panel_info); } diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h index 47f14c2ec96c..82f085a15b82 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h +++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h @@ -52,6 +52,7 @@ #define MDSS_MDP_REG_SPLIT_DISPLAY_EN 0x002F4 #define MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL 0x002F8 #define MDSS_MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTRL 0x003F0 +#define MDSS_MDP_REG_DCE_SEL 0x00450 #define MDSS_INTF_DSI 0x1 #define MDSS_INTF_HDMI 0x3 @@ -578,6 +579,32 @@ enum mdss_mdp_pingpong_index { #define MDSS_MDP_REG_PP_FBC_MODE 0x034 #define MDSS_MDP_REG_PP_FBC_BUDGET_CTL 0x038 #define MDSS_MDP_REG_PP_FBC_LOSSY_MODE 0x03C +#define MDSS_MDP_REG_PP_DSC_MODE 0x0a0 +#define MDSS_MDP_REG_PP_DCE_DATA_IN_SWAP 0x0ac +#define MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP 0x0c8 + +#define MDSS_MDP_DSC_0_OFFSET 0x80000 +#define MDSS_MDP_DSC_1_OFFSET 0x80400 + +#define MDSS_MDP_REG_DSC_COMMON_MODE 0x000 +#define MDSS_MDP_REG_DSC_ENC 0x004 +#define MDSS_MDP_REG_DSC_PICTURE 0x008 +#define MDSS_MDP_REG_DSC_SLICE 0x00c +#define MDSS_MDP_REG_DSC_CHUNK_SIZE 0x010 +#define MDSS_MDP_REG_DSC_DELAY 0x014 +#define MDSS_MDP_REG_DSC_SCALE_INITIAL 0x018 +#define MDSS_MDP_REG_DSC_SCALE_DEC_INTERVAL 0x01c +#define MDSS_MDP_REG_DSC_SCALE_INC_INTERVAL 0x020 +#define MDSS_MDP_REG_DSC_FIRST_LINE_BPG_OFFSET 0x024 +#define MDSS_MDP_REG_DSC_BPG_OFFSET 0x028 +#define MDSS_MDP_REG_DSC_DSC_OFFSET 0x02c +#define MDSS_MDP_REG_DSC_FLATNESS 0x030 +#define MDSS_MDP_REG_DSC_RC_MODEL_SIZE 0x034 +#define MDSS_MDP_REG_DSC_RC 0x038 +#define MDSS_MDP_REG_DSC_RC_BUF_THRESH 0x03c +#define MDSS_MDP_REG_DSC_RANGE_MIN_QP 0x074 +#define MDSS_MDP_REG_DSC_RANGE_MAX_QP 0x0b0 +#define MDSS_MDP_REG_DSC_RANGE_BPG_OFFSET 0x0ec #define MDSS_MDP_REG_SMP_ALLOC_W0 0x00080 #define MDSS_MDP_REG_SMP_ALLOC_R0 0x00130 diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 844f34391931..4b0440cb899b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -1258,6 +1258,7 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, struct intf_timing_params itp = {0}; u32 dst_bpp; struct mdss_data_type *mdata = ctl->mdata; + struct dsc_desc *dsc = NULL; ctx->intf_type = ctl->intf_type; init_completion(&ctx->vsync_comp); @@ -1298,6 +1299,9 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, pr_debug("%s: cdm not supported\n", __func__); } + if (pinfo->compression_mode == COMPRESSION_DSC) + dsc = &pinfo->dsc; + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctx->intf_num, mdss_mdp_video_vsync_intr_done, ctl); @@ -1322,6 +1326,11 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, itp.yres = pinfo->yres + pinfo->lcdc.border_top + pinfo->lcdc.border_bottom; + if (dsc) { /* compressed */ + itp.width = dsc->pclk_per_line; + itp.xres = dsc->pclk_per_line; + } + itp.h_back_porch = pinfo->lcdc.h_back_porch; itp.h_front_porch = pinfo->lcdc.h_front_porch; itp.v_back_porch = pinfo->lcdc.v_back_porch; |
