|
@@ -814,7 +814,9 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp,
|
|
|
uint32_t status_reg = 0;
|
|
|
struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
|
|
|
|
|
|
- status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16;
|
|
|
+ REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
|
|
|
+ &status_reg);
|
|
|
+
|
|
|
if (status_reg == 9) {
|
|
|
*ram_a_inuse = true;
|
|
|
ret = true;
|
|
@@ -825,6 +827,28 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp,
|
|
|
+ bool *ram_a_inuse)
|
|
|
+{
|
|
|
+ bool in_use = false;
|
|
|
+ uint32_t status_reg = 0;
|
|
|
+ struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
|
|
|
+
|
|
|
+ REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
|
|
|
+ &status_reg);
|
|
|
+
|
|
|
+ // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB
|
|
|
+ if (status_reg == 1 || status_reg == 3 || status_reg == 4) {
|
|
|
+ *ram_a_inuse = true;
|
|
|
+ in_use = true;
|
|
|
+ // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB
|
|
|
+ } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) {
|
|
|
+ *ram_a_inuse = false;
|
|
|
+ in_use = true;
|
|
|
+ }
|
|
|
+ return in_use;
|
|
|
+}
|
|
|
+
|
|
|
static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp,
|
|
|
bool use_ram_a)
|
|
|
{
|
|
@@ -855,6 +879,61 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp,
|
|
|
dcn10_degamma_ram_select(ipp, !is_ram_a);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Input gamma LUT currently supports 256 values only. This means input color
|
|
|
+ * can have a maximum of 8 bits per channel (= 256 possible values) in order to
|
|
|
+ * have a one-to-one mapping with the LUT. Truncation will occur with color
|
|
|
+ * values greater than 8 bits.
|
|
|
+ *
|
|
|
+ * In the future, this function should support additional input gamma methods,
|
|
|
+ * such as piecewise linear mapping, and input gamma bypass.
|
|
|
+ */
|
|
|
+void dcn10_ipp_program_input_lut(
|
|
|
+ struct input_pixel_processor *ipp,
|
|
|
+ const struct dc_gamma *gamma)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
|
|
|
+ bool rama_occupied = false;
|
|
|
+ uint32_t ram_num;
|
|
|
+ // Power on LUT memory.
|
|
|
+ REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1);
|
|
|
+ dcn10_ipp_enable_cm_block(ipp);
|
|
|
+ // Determine whether to use RAM A or RAM B
|
|
|
+ dcn10_ingamma_ram_inuse(ipp, &rama_occupied);
|
|
|
+ if (!rama_occupied)
|
|
|
+ REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0);
|
|
|
+ else
|
|
|
+ REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1);
|
|
|
+ // RW mode is 256-entry LUT
|
|
|
+ REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0);
|
|
|
+ // IGAM Input format should be 8 bits per channel.
|
|
|
+ REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0);
|
|
|
+ // Do not mask any R,G,B values
|
|
|
+ REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7);
|
|
|
+ // LUT-256, unsigned, integer, new u0.12 format
|
|
|
+ REG_UPDATE_3(
|
|
|
+ CM_IGAM_CONTROL,
|
|
|
+ CM_IGAM_LUT_FORMAT_R, 3,
|
|
|
+ CM_IGAM_LUT_FORMAT_G, 3,
|
|
|
+ CM_IGAM_LUT_FORMAT_B, 3);
|
|
|
+ // Start at index 0 of IGAM LUT
|
|
|
+ REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0);
|
|
|
+ for (i = 0; i < INPUT_LUT_ENTRIES; i++) {
|
|
|
+ REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
|
|
|
+ gamma->red[i]);
|
|
|
+ REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
|
|
|
+ gamma->green[i]);
|
|
|
+ REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
|
|
|
+ gamma->blue[i]);
|
|
|
+ }
|
|
|
+ // Power off LUT memory
|
|
|
+ REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0);
|
|
|
+ // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB
|
|
|
+ REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2);
|
|
|
+ REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num);
|
|
|
+}
|
|
|
+
|
|
|
/*****************************************/
|
|
|
/* Constructor, Destructor */
|
|
|
/*****************************************/
|
|
@@ -869,6 +948,7 @@ static const struct ipp_funcs dcn10_ipp_funcs = {
|
|
|
.ipp_cursor_set_attributes = dcn10_cursor_set_attributes,
|
|
|
.ipp_cursor_set_position = dcn10_cursor_set_position,
|
|
|
.ipp_set_degamma = dcn10_ipp_set_degamma,
|
|
|
+ .ipp_program_input_lut = dcn10_ipp_program_input_lut,
|
|
|
.ipp_full_bypass = dcn10_ipp_full_bypass,
|
|
|
.ipp_setup = dcn10_ipp_cnv_setup,
|
|
|
.ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl,
|