drm/rockchip: vop2: get gamma config from dts

sample:

/ {
	dsp_lut0: dsp-lut0 {
		gamma-lut = <...>;
	};

	dsp_lut1: dsp-lut1 {
		gamma-lut = <...>;
	};
};

&vp0 {
	dsp-lut = <&dsp_lut0>;
};

&vp1 {
	dsp-lut = <&dsp_lut1>;
};

Signed-off-by: Sandy Huang <hjc@rock-chips.com>
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Change-Id: Ifca948f102abe73e925744aa792b6e1f87579761
This commit is contained in:
Sandy Huang
2024-04-08 19:59:58 +08:00
committed by Tao Huang
parent 83dbc34b20
commit dc65fd7c5f

View File

@@ -12406,17 +12406,18 @@ static int vop2_gamma_init(struct vop2 *vop2)
continue;
vp->gamma_lut_len = vp_data->gamma_lut_len;
vp->lut_dma_rid = vp_data->lut_dma_rid;
vp->lut = devm_kmalloc_array(dev, lut_len, sizeof(*vp->lut),
GFP_KERNEL);
if (!vp->lut)
return -ENOMEM;
if (!vp->gamma_lut_active) {
vp->lut = devm_kmalloc_array(dev, lut_len, sizeof(*vp->lut), GFP_KERNEL);
if (!vp->lut)
return -ENOMEM;
for (j = 0; j < lut_len; j++) {
u32 b = j * lut_len * lut_len;
u32 g = j * lut_len;
u32 r = j;
for (j = 0; j < lut_len; j++) {
u32 b = j * lut_len * lut_len;
u32 g = j * lut_len;
u32 r = j;
vp->lut[j] = r | g | b;
vp->lut[j] = r | g | b;
}
}
drm_mode_crtc_set_gamma_size(crtc, lut_len);
@@ -13511,6 +13512,84 @@ static inline void rockchip_vop2_devfreq_uninit(struct vop2 *vop2)
}
#endif
static int vop2_of_get_gamma_lut(struct vop2 *vop2, struct device_node *dsp_lut_node, int vp_id)
{
const struct vop2_data *vop2_data = vop2->data;
const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp_id];
struct vop2_video_port *vp = &vop2->vps[vp_id];
struct property *prop;
u32 lut_len = vp_data->gamma_lut_len;
int length = 0;
int i = 0, j = 0;
int ret = 0;
if (!vop2->lut_regs || !lut_len)
return 0;
prop = of_find_property(dsp_lut_node, "gamma-lut", &length);
if (!prop)
return -EINVAL;
vp->lut = devm_kmalloc_array(vop2->dev, lut_len, sizeof(*vp->lut), GFP_KERNEL);
if (!vp->lut)
return -ENOMEM;
length >>= 2;
if (length != vp_data->gamma_lut_len) {
u32 r, g, b;
u32 *lut;
lut = kmalloc_array(length, sizeof(*lut), GFP_KERNEL);
if (!lut) {
devm_kfree(vop2->dev, vp->lut);
vp->lut = NULL;
return -ENOMEM;
}
ret = of_property_read_u32_array(dsp_lut_node, "gamma-lut", lut, length);
if (ret) {
devm_kfree(vop2->dev, vp->lut);
vp->lut = NULL;
kfree(lut);
return -EINVAL;
}
/*
* In order to achieve the same gamma correction effect in different
* platforms, the following conversion helps to translate from 8bit
* gamma table with 256 parameters to 10bit gamma with 1024 parameters.
*/
for (i = 0; i < lut_len; i++) {
j = i * length / lut_len;
r = lut[j] / length / length * lut_len / length;
g = lut[j] / length % length * lut_len / length;
b = lut[j] % length * lut_len / length;
vp->lut[i] = r * lut_len * lut_len + g * lut_len + b;
}
kfree(lut);
} else {
of_property_read_u32_array(dsp_lut_node, "gamma-lut", vp->lut, vp->gamma_lut_len);
}
vp->gamma_lut_active = true;
return 0;
}
static void vop2_of_get_dsp_lut(struct vop2 *vop2, struct device_node *vp_node, int vp_id)
{
struct device_node *dsp_lut_node;
int ret = 0;
dsp_lut_node = of_parse_phandle(vp_node, "dsp-lut", 0);
if (dsp_lut_node) {
ret = vop2_of_get_gamma_lut(vop2, dsp_lut_node, vp_id);
if (ret)
DRM_ERROR("load vp%d gamma-lut failed\n", vp_id);
}
}
static int vop2_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -13708,6 +13787,8 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
vop2->vps[vp_id].mcu_timing.mcu_hold_mode = val;
}
vop2_of_get_dsp_lut(vop2, child, vp_id);
if (vop2_get_vp_of_status(child))
enabled_vp_mask |= BIT(vp_id);
}