diff options
author | Kuogee Hsieh <khsieh@codeaurora.org> | 2015-04-15 10:53:53 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:40:44 -0700 |
commit | e9181896cfb0ea58f0cc8e511dcff96efa474584 (patch) | |
tree | b897e7b368c6d5c8e7a3a1a8312a3552cdfe26c4 | |
parent | 262c304acbf7d59583c34054cf56d8a91a979f5b (diff) |
msm: mdss: add DSC parameters calculation
Add DSC run time parameters calculation base on some
predefined parameters input from dtsi. Also configure
DSI controller properly if it is enabled.
Change-Id: I24b7a2cb829084f76a159b54170b87d051c9eac6
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
-rw-r--r-- | Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt | 30 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 7 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_host.c | 42 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 370 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 87 |
5 files changed, 481 insertions, 55 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index e0b755ceae5b..e50ade24be0f 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -398,6 +398,25 @@ Optional properties: - qcom,panel-ack-disabled: A boolean property to indicate, whether we need to wait for any ACK from the panel for any commands that we send. - qcom,mdss-dsi-force-clock-lane-hs: Boolean to force dsi clock lanes to HS mode always. +- qcom,mdss-dsi-compression: Select compression mode for panel. + "fbc" - frame buffer compression + "dsc" - display stream compression. +- qcom,mdss-dsc-slice-height: An integer value indicates the dsc slice height. +- qcom,mdss-dsc-slice-width: An integer value indicates the dsc slice width. +- qcom,mdss-dsc-slice-per-pkt: An integer value indicates the slice per dsi packet. +- qcom,mdss-dsc-bit-per-component: An integer value indicates the bits per component before compression. +- qcom,mdss-dsc-bit-per-pixel: An integer value indicates the bits per pixel after compression. +- qcom,mdss-dsc-block-prediction-enable: A boolean value to enable/disable the block prediction at decoder. +- qcom,mdss-dsc-ich-reset-value: An integer value defines the Indexed Color History reset value. +- qcom,mdss-dsc-ich-reset-override: An integer value defines the Indexed Color History for each line in + slice. +- qcom,mdss-dsc-data-path-mode: Select the dsc data path mode. + "1p1d" - Single panel and single DSI + "merge-1p2d" - Merge two DSI output to single panel + "split-1p2d" - This is fb split mode which have two encoder work + in tandem to compress large image. +- qcom,mdss-dsc-config-by-manufacture-cmd: A boolean to indicates panel use manufacture command to setup pps + instead of standard dcs type 0x0A. Note, if a given optional qcom,* binding is not present, then the driver will configure the default values specified. @@ -539,5 +558,16 @@ Example: <128 240 64>; qcom,mdss-dsi-panel-orientation = "180" qcom,mdss-dsi-force-clock-lane-hs; + qcom,mdss-dsi-compression = "dsc"; + qcom,mdss-dsc-slice-height = <16>; + qcom,mdss-dsc-slice-width = <720>; + qcom,mdss-dsc-slice-per-pkt = <2>; + qcom,mdss-dsc-bit-per-component = <8>; + qcom,mdss-dsc-bit-per-pixel = <8>; + qcom,mdss-dsc-block-prediction-enable; + qcom,mdss-dsc-ich-reset-value = <0>; + qcom,mdss-dsc-ich-reset-override = <0>; + qcom,mdss-dsc-data-path-mode = "1p1d"; + qcom,mdss-dsc-config-by-manufacture-cmd; }; }; diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index d9715f70c419..dc208e6d2494 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -288,6 +288,12 @@ enum { #define DSI_EV_STOP_HS_CLK_LANE 0x40000000 #define DSI_EV_MDP_BUSY_RELEASE 0x80000000 +#define MDSS_DSI_VIDEO_COMPRESSION_MODE_CTRL 0x02a0 +#define MDSS_DSI_VIDEO_COMPRESSION_MODE_CTRL2 0x02a4 +#define MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL 0x02a8 +#define MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x02ac +#define MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x02b0 + struct mdss_dsi_ctrl_pdata { int ndx; /* panel_num */ int (*on) (struct mdss_panel_data *pdata); @@ -343,6 +349,7 @@ struct mdss_dsi_ctrl_pdata { bool dmap_iommu_map; bool panel_bias_vreg; bool dsi_irq_line; + bool dcs_cmd_insert; atomic_t te_irq_ready; bool cmd_clk_ln_recovery_en; diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index dcae9d1d5eed..50e09ba105b5 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -1027,11 +1027,45 @@ int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) return ret; } +static void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, + struct dsc_desc *dsc) +{ + u32 data; + + if (ctrl->panel_mode == DSI_VIDEO_MODE) { + MIPI_OUTP((ctrl->ctrl_base) + + MDSS_DSI_VIDEO_COMPRESSION_MODE_CTRL2, 0); + data = dsc->bytes_per_pkt << 16; + data |= (0x0b << 8); /* dtype of compressed image */ + data |= (dsc->pkt_per_line - 1) << 6; + data |= dsc->eol_byte_num << 4; + data |= 1; /* enable */ + MIPI_OUTP((ctrl->ctrl_base) + + MDSS_DSI_VIDEO_COMPRESSION_MODE_CTRL, data); + } else { + /* strem 0 */ + MIPI_OUTP((ctrl->ctrl_base) + + MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL3, 0); + + MIPI_OUTP((ctrl->ctrl_base) + + MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL2, + dsc->bytes_per_pkt); + + data = 0x0b << 8; + data |= (dsc->pkt_per_line - 1) << 6; + data |= dsc->eol_byte_num << 4; + data |= 1; /* enable */ + MIPI_OUTP((ctrl->ctrl_base) + + MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL, data); + } +} + static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; + struct dsc_desc *dsc = NULL; u32 clk_rate; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, dst_bpp; @@ -1043,6 +1077,8 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) panel_data); pinfo = &pdata->panel_info; + if (pinfo->compression_mode == COMPRESSION_DSC) + dsc = &pinfo->dsc; clk_rate = pdata->panel_info.clk_rate; clk_rate = min(clk_rate, pdata->panel_info.clk_max); @@ -1060,6 +1096,9 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) pdata->panel_info.bpp); height = pdata->panel_info.yres; + if (dsc) /* compressed */ + width = dsc->pclk_per_line; + if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { dummy_xres = mult_frac((pdata->panel_info.lcdc.border_left + pdata->panel_info.lcdc.border_right), @@ -1122,6 +1161,9 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, stream_total); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, stream_total); } + + if (dsc) /* compressed */ + mdss_dsi_dsc_config(ctrl_pdata, dsc); } void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl) diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 735b4d60c9d1..5fccab2c299a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -27,10 +27,21 @@ #define DT_CMD_HDR 6 #define MIN_REFRESH_RATE 30 +#define CEIL(x, y) (((x) + ((y)-1)) / (y)) + #define VSYNC_DELAY msecs_to_jiffies(17) DEFINE_LED_TRIGGER(bl_led_trigger); +static u32 dsc_rc_buf_thresh[] = {0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, + 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e}; +static char dsc_rc_range_min_qp[] = {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, + 5, 5, 7, 13}; +static char dsc_rc_range_max_qp[] = {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, + 12, 13, 13, 15}; +static char dsc_rc_range_bpg_offset[] = {2, 0, 0, -2, -4, -6, -8, -8, + -8, -10, -10, -12, -12, -12, -12}; + void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl) { if (ctrl->pwm_pmi) @@ -628,7 +639,7 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); - pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx); + pr_debug("%s: ndx=%d\n", __func__, ctrl->ndx); if (pinfo->dcs_cmd_by_left) { if (ctrl->ndx != DSI_CTRL_LEFT) @@ -641,6 +652,9 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) (pinfo->mipi.boot_mode != pinfo->mipi.mode)) on_cmds = &ctrl->post_dms_on_cmds; + pr_debug("%s: ndx=%d cmd_cnt=%d\n", __func__, + ctrl->ndx, on_cmds->cmd_cnt); + if (on_cmds->cmd_cnt) mdss_dsi_panel_cmds_send(ctrl, on_cmds); @@ -938,70 +952,324 @@ int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing, return rc; } - static int mdss_dsi_parse_fbc_params(struct device_node *np, struct mdss_panel_info *panel_info) { - int rc, fbc_enabled = 0; + int rc; u32 tmp; - fbc_enabled = of_property_read_bool(np, "qcom,mdss-dsi-fbc-enable"); - if (fbc_enabled) { - pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__); - panel_info->fbc.enabled = 1; - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bpp", &tmp); - panel_info->fbc.target_bpp = (!rc ? tmp : panel_info->bpp); - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-packing", + pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__); + panel_info->fbc.enabled = 1; + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bpp", &tmp); + panel_info->fbc.target_bpp = (!rc ? tmp : panel_info->bpp); + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-packing", &tmp); - panel_info->fbc.comp_mode = (!rc ? tmp : 0); - panel_info->fbc.qerr_enable = of_property_read_bool(np, + panel_info->fbc.comp_mode = (!rc ? tmp : 0); + panel_info->fbc.qerr_enable = of_property_read_bool(np, "qcom,mdss-dsi-fbc-quant-error"); - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bias", &tmp); - panel_info->fbc.cd_bias = (!rc ? tmp : 0); - panel_info->fbc.pat_enable = of_property_read_bool(np, + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bias", &tmp); + panel_info->fbc.cd_bias = (!rc ? tmp : 0); + panel_info->fbc.pat_enable = of_property_read_bool(np, "qcom,mdss-dsi-fbc-pat-mode"); - panel_info->fbc.vlc_enable = of_property_read_bool(np, + panel_info->fbc.vlc_enable = of_property_read_bool(np, "qcom,mdss-dsi-fbc-vlc-mode"); - panel_info->fbc.bflc_enable = of_property_read_bool(np, + panel_info->fbc.bflc_enable = of_property_read_bool(np, "qcom,mdss-dsi-fbc-bflc-mode"); - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-h-line-budget", + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-h-line-budget", &tmp); - panel_info->fbc.line_x_budget = (!rc ? tmp : 0); - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-budget-ctrl", + panel_info->fbc.line_x_budget = (!rc ? tmp : 0); + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-budget-ctrl", &tmp); - panel_info->fbc.block_x_budget = (!rc ? tmp : 0); - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-block-budget", + panel_info->fbc.block_x_budget = (!rc ? tmp : 0); + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-block-budget", &tmp); - panel_info->fbc.block_budget = (!rc ? tmp : 0); - rc = of_property_read_u32(np, - "qcom,mdss-dsi-fbc-lossless-threshold", &tmp); - panel_info->fbc.lossless_mode_thd = (!rc ? tmp : 0); - rc = of_property_read_u32(np, - "qcom,mdss-dsi-fbc-lossy-threshold", &tmp); - panel_info->fbc.lossy_mode_thd = (!rc ? tmp : 0); - rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-rgb-threshold", + panel_info->fbc.block_budget = (!rc ? tmp : 0); + rc = of_property_read_u32(np, + "qcom,mdss-dsi-fbc-lossless-threshold", &tmp); + panel_info->fbc.lossless_mode_thd = (!rc ? tmp : 0); + rc = of_property_read_u32(np, + "qcom,mdss-dsi-fbc-lossy-threshold", &tmp); + panel_info->fbc.lossy_mode_thd = (!rc ? tmp : 0); + rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-rgb-threshold", &tmp); - panel_info->fbc.lossy_rgb_thd = (!rc ? tmp : 0); - rc = of_property_read_u32(np, - "qcom,mdss-dsi-fbc-lossy-mode-idx", &tmp); - panel_info->fbc.lossy_mode_idx = (!rc ? tmp : 0); - rc = of_property_read_u32(np, - "qcom,mdss-dsi-fbc-slice-height", &tmp); - panel_info->fbc.slice_height = (!rc ? tmp : 0); - panel_info->fbc.pred_mode = of_property_read_bool(np, - "qcom,mdss-dsi-fbc-2d-pred-mode"); - panel_info->fbc.enc_mode = of_property_read_bool(np, - "qcom,mdss-dsi-fbc-ver2-mode"); - rc = of_property_read_u32(np, - "qcom,mdss-dsi-fbc-max-pred-err", &tmp); - panel_info->fbc.max_pred_err = (!rc ? tmp : 0); - } else { - pr_debug("%s:%d Panel does not support FBC.\n", - __func__, __LINE__); - panel_info->fbc.enabled = 0; - panel_info->fbc.target_bpp = - panel_info->bpp; + panel_info->fbc.lossy_rgb_thd = (!rc ? tmp : 0); + rc = of_property_read_u32(np, + "qcom,mdss-dsi-fbc-lossy-mode-idx", &tmp); + panel_info->fbc.lossy_mode_idx = (!rc ? tmp : 0); + rc = of_property_read_u32(np, + "qcom,mdss-dsi-fbc-slice-height", &tmp); + panel_info->fbc.slice_height = (!rc ? tmp : 0); + panel_info->fbc.pred_mode = of_property_read_bool(np, + "qcom,mdss-dsi-fbc-2d-pred-mode"); + panel_info->fbc.enc_mode = of_property_read_bool(np, + "qcom,mdss-dsi-fbc-ver2-mode"); + rc = of_property_read_u32(np, + "qcom,mdss-dsi-fbc-max-pred-err", &tmp); + panel_info->fbc.max_pred_err = (!rc ? tmp : 0); + + panel_info->compression_mode = COMPRESSION_FBC; + + return 0; +} + +void mdss_dsc_parameters_calc(struct mdss_panel_info *pinfo) +{ + struct dsc_desc *dsc; + int bpp, bpc; + int mux_words_size; + int groups_per_line, groups_total; + int min_rate_buffer_size; + int hrd_delay; + int pre_num_extra_mux_bits, num_extra_mux_bits; + int slice_bits; + int target_bpp_x16; + int data; + int final_value, final_scale; + int slice_per_line, bytes_in_slice, total_bytes; + + dsc = &pinfo->dsc; + dsc->rc_model_size = 8192; /* rate_buffer_size */ + dsc->first_line_bpg_offset = 12; + dsc->min_qp_flatness = 3; + dsc->max_qp_flatness = 12; + dsc->line_buf_depth = 9; + dsc->max_qp_flatness = 12; + dsc->min_qp_flatness = 3; + + dsc->pkt_per_line = 1; + + dsc->edge_factor = 6; + dsc->quant_incr_limit0 = 11; + dsc->quant_incr_limit1 = 11; + dsc->tgt_offset_hi = 3; + dsc->tgt_offset_lo = 3; + + dsc->buf_thresh = dsc_rc_buf_thresh; + dsc->range_min_qp = dsc_rc_range_min_qp; + dsc->range_max_qp = dsc_rc_range_max_qp; + dsc->range_bpg_offset = dsc_rc_range_bpg_offset; + + dsc->slice_per_pkt = 1; + dsc->initial_lines = 2; + + dsc->pic_width = pinfo->xres; + dsc->pic_height = pinfo->yres; + + bpp = dsc->bpp; + bpc = dsc->bpc; + + if (bpp == 8) + dsc->initial_offset = 6144; + else + dsc->initial_offset = 2048; /* bpp = 12 */ + + if (bpc == 8) + mux_words_size = 48; + else + mux_words_size = 64; /* bpc == 12 */ + + slice_per_line = dsc->pic_width / dsc->slice_width; + bytes_in_slice = CEIL(dsc->pic_width, slice_per_line); + + data = 0; + bytes_in_slice *= dsc->bpp; /* compressed */ + if (bytes_in_slice % 8) + data++; + + bytes_in_slice /= 8; + if (data) + bytes_in_slice++; + + total_bytes = bytes_in_slice * slice_per_line; + dsc->eol_byte_num = total_bytes % 3; + dsc->pclk_per_line = total_bytes / 3; + if (dsc->eol_byte_num) + dsc->pclk_per_line++; + + dsc->slice_last_group_size = 3 - dsc->eol_byte_num; + + pr_debug("%s: pclk_per_line=%d total_bytes=%d eol_byte_num=%d\n", + __func__, dsc->pclk_per_line, total_bytes, dsc->eol_byte_num); + + dsc->bytes_per_pkt = bytes_in_slice * dsc->slice_per_pkt; + + dsc->det_thresh_flatness = 7 + (bpc - 8); + + dsc->initial_xmit_delay = dsc->rc_model_size / (2 * bpp); + + groups_per_line = CEIL(dsc->slice_width, 3); + + dsc->chunk_size = dsc->slice_width * bpp / 8; + if ((dsc->slice_width * bpp) % 8) + dsc->chunk_size++; + + dsc->pkt_per_line = CEIL(dsc->pic_width, dsc->slice_width); + + /* rbs-min */ + min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset + + dsc->initial_xmit_delay * bpp + + groups_per_line * dsc->first_line_bpg_offset; + + hrd_delay = CEIL(min_rate_buffer_size, bpp); + + dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay; + + dsc->initial_scale_value = 8 * dsc->rc_model_size / + (dsc->rc_model_size - dsc->initial_offset); + + slice_bits = 8 * dsc->chunk_size * dsc->slice_height; + + groups_total = groups_per_line * dsc->slice_height; + + data = dsc->first_line_bpg_offset * 2048; + + dsc->nfl_bpg_offset = CEIL(data, (dsc->slice_height - 1)); + + pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * bpc + 4) - 2); + + num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size - + ((slice_bits - pre_num_extra_mux_bits) % mux_words_size)); + + data = 2048 * (dsc->rc_model_size - dsc->initial_offset + + num_extra_mux_bits); + dsc->slice_bpg_offset = CEIL(data, groups_total); + + /* bpp * 16 + 0.5 */ + data = bpp * 16; + data *= 2; + data++; + data /= 2; + target_bpp_x16 = data; + + data = (dsc->initial_xmit_delay * target_bpp_x16) / 16; + final_value = dsc->rc_model_size - data + num_extra_mux_bits; + + final_scale = 8 * dsc->rc_model_size / + (dsc->rc_model_size - final_value); + + dsc->final_offset = final_value; + + data = (final_scale - 9) * (dsc->nfl_bpg_offset + + dsc->slice_bpg_offset); + dsc->scale_increment_interval = (2048 * dsc->final_offset) / data; + + dsc->scale_decrement_interval = groups_per_line / + (dsc->initial_scale_value - 8); + + pr_debug("%s: initial_xmit_delay=%d\n", __func__, + dsc->initial_xmit_delay); + + pr_debug("%s: bpg_offset, nfl=%d slice=%d\n", __func__, + dsc->nfl_bpg_offset, dsc->slice_bpg_offset); + + pr_debug("%s: groups_per_line=%d chunk_size=%d\n", __func__, + groups_per_line, dsc->chunk_size); + pr_debug("%s:min_rate_buffer_size=%d hrd_delay=%d\n", __func__, + min_rate_buffer_size, hrd_delay); + pr_debug("%s:initial_dec_delay=%d initial_scale_value=%d\n", __func__, + dsc->initial_dec_delay, dsc->initial_scale_value); + pr_debug("%s:slice_bits=%d, groups_total=%d\n", __func__, + slice_bits, groups_total); + pr_debug("%s: first_line_bgp_offset=%d slice_height=%d\n", __func__, + dsc->first_line_bpg_offset, dsc->slice_height); + pr_debug("%s:final_value=%d final_scale=%d\n", __func__, + final_value, final_scale); + pr_debug("%s: sacle_increment_interval=%d scale_decrement_interval=%d\n", + __func__, dsc->scale_increment_interval, + dsc->scale_decrement_interval); +} + +static int mdss_dsi_parse_dsc_params(struct device_node *np, + struct mdss_panel_info *pinfo) +{ + struct dsc_desc *dsc; + u32 data; + const char *cp; + int rc = 0; + + dsc = &pinfo->dsc; + rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-height", &data); + if (rc) + goto end; + dsc->slice_height = data; + + rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-width", &data); + if (rc) + goto end; + dsc->slice_width = data; + + rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-per-pkt", &data); + if (rc) + goto end; + dsc->slice_per_pkt = data; + + pr_debug("%s: slice h=%d w=%d s_pkt=%d\n", __func__, + dsc->slice_height, dsc->slice_width, dsc->slice_per_pkt); + + rc = of_property_read_u32(np, "qcom,mdss-dsc-bit-per-component", &data); + if (rc) + goto end; + dsc->bpc = data; + + rc = of_property_read_u32(np, "qcom,mdss-dsc-bit-per-pixel", &data); + if (rc) + goto end; + dsc->bpp = data; + + pr_debug("%s: bpc=%d bpp=%d\n", __func__, + dsc->bpc, dsc->bpp); + + rc = of_property_read_u32(np, "qcom,mdss-dsc-ich-reset-value", &data); + if (rc) + goto end; + dsc->ich_reset_value = data; + + rc = of_property_read_u32(np, "qcom,mdss-dsc-ich-reset-override", + &data); + if (rc) + goto end; + dsc->ich_reset_override = data; + + dsc->data_path_model = DSC_PATH_1P1D; /* default */ + cp = of_get_property(np, "qcom,mdss-dsc-data-path-mode", NULL); + if (cp && !strcmp(cp, "merge_1p1d")) + dsc->data_path_model = DSC_PATH_MERGE_1P1D; + else if (cp && !strcmp(cp, "split_1p2d")) + dsc->data_path_model = DSC_PATH_SPLIT_1P2D; + + dsc->block_pred_enable = of_property_read_bool(np, + "qcom,mdss-dsc-block-prediction-enable"); + + dsc->enable_422 = 0; + dsc->convert_rgb = 1; + + dsc->config_by_manufacture_cmd = of_property_read_bool(np, + "qcom,mdss-dsc-config-by-manufacture-cmd"); + + mdss_dsc_parameters_calc(pinfo); + + pinfo->compression_mode = COMPRESSION_DSC; + +end: + return rc; +} + +static int mdss_dsi_parse_compression_params(struct device_node *np, + struct mdss_panel_info *pinfo) +{ + const char *data; + + pinfo->fbc.enabled = 0; + pinfo->fbc.target_bpp = pinfo->bpp; + + data = of_get_property(np, "qcom,mdss-dsi-compression", NULL); + if (data) { + if (!strcmp(data, "dsc")) + mdss_dsi_parse_dsc_params(np, pinfo); + else if (!strcmp(data, "fbc")) + mdss_dsi_parse_fbc_params(np, pinfo); } + return 0; } @@ -1797,7 +2065,7 @@ static int mdss_panel_parse_dt(struct device_node *np, mdss_dsi_parse_lane_swap(np, &(pinfo->mipi.dlane_swap)); - mdss_dsi_parse_fbc_params(np, pinfo); + mdss_dsi_parse_compression_params(np, pinfo); mdss_panel_parse_te_params(np, pinfo); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index d6a49e2346b3..1b016dc5305d 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -347,6 +347,75 @@ struct lvds_panel_info { char channel_swap; }; +enum { + DSC_PATH_1P1D, + DSC_PATH_MERGE_1P1D, + DSC_PATH_SPLIT_1P2D +}; + +enum { + COMPRESSION_NONE, + COMPRESSION_DSC, + COMPRESSION_FBC +}; + +struct dsc_desc { + int data_path_model; /* multiplex + split_panel */ + int ich_reset_value; + int ich_reset_override; + int initial_lines; + int slice_last_group_size; + int bpp; /* target bit per pixel */ + int bpc; /* bit per component */ + int line_buf_depth; + bool config_by_manufacture_cmd; + bool block_pred_enable; + int enable_422; + int convert_rgb; + int input_10_bits; + int slice_per_pkt; + + int pic_height; + int pic_width; + int slice_height; + int slice_width; + int chunk_size; + + int pkt_per_line; + int bytes_per_pkt; + int eol_byte_num; + int pclk_per_line; /* width */ + + int initial_dec_delay; + int initial_xmit_delay; + + int initial_scale_value; + int scale_decrement_interval; + int scale_increment_interval; + + int first_line_bpg_offset; + int nfl_bpg_offset; + int slice_bpg_offset; + + int initial_offset; + int final_offset; + + int rc_model_size; /* rate_buffer_size */ + + int det_thresh_flatness; + int max_qp_flatness; + int min_qp_flatness; + int edge_factor; + int quant_incr_limit0; + int quant_incr_limit1; + int tgt_offset_hi; + int tgt_offset_lo; + u32 *buf_thresh; + char *range_min_qp; + char *range_max_qp; + char *range_bpg_offset; +}; + struct fbc_panel_info { u32 enabled; u32 target_bpp; @@ -437,6 +506,7 @@ struct mdss_panel_info { struct ion_handle *splash_ihdl; int panel_power_state; int blank_state; + int compression_mode; uint32_t panel_dead; u32 panel_force_dead; @@ -450,6 +520,7 @@ struct mdss_panel_info { char panel_name[MDSS_MAX_PANEL_LEN]; struct mdss_mdp_pp_tear_check te; + struct dsc_desc dsc; struct lcd_panel_info lcdc; struct fbc_panel_info fbc; struct mipi_panel_info mipi; @@ -553,7 +624,7 @@ static inline int mdss_panel_get_vtotal(struct mdss_panel_info *pinfo) /* * mdss_panel_get_htotal() - return panel horizontal width * @pinfo: Pointer to panel info containing all panel information - * @consider_fbc: true to factor fbc settings, false to ignore. + * @compression: true to factor fbc settings, false to ignore. * * Returns the total width of the panel including any blanking regions * which are not visible to user but used for calculations. For certain @@ -561,14 +632,22 @@ static inline int mdss_panel_get_vtotal(struct mdss_panel_info *pinfo) * calculation, the appropriate flag can be passed. */ static inline int mdss_panel_get_htotal(struct mdss_panel_info *pinfo, bool - consider_fbc) + compression) { + struct dsc_desc *dsc = NULL; + int adj_xres = pinfo->xres + pinfo->lcdc.border_left + pinfo->lcdc.border_right; - if (consider_fbc && pinfo->fbc.enabled) - adj_xres = mult_frac(adj_xres, + if (compression) { + if (pinfo->compression_mode == COMPRESSION_DSC) { + dsc = &pinfo->dsc; + adj_xres = dsc->pclk_per_line; + } else if (pinfo->fbc.enabled) { + adj_xres = mult_frac(adj_xres, pinfo->fbc.target_bpp, pinfo->bpp); + } + } return adj_xres + pinfo->lcdc.h_back_porch + pinfo->lcdc.h_front_porch + |