mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
media: i2c: rk628: add color_range/color_space interface.
Change-Id: I9f2633f8ff4f9f2b3e9d6c02b3865eff125f30a5 Signed-off-by: Wangqiang Guo <kay.guo@rock-chips.com>
This commit is contained in:
@@ -106,7 +106,6 @@ struct rk628_csi {
|
||||
u32 stream_state;
|
||||
int hdmirx_irq;
|
||||
int plugin_irq;
|
||||
int avi_rdy;
|
||||
bool nosignal;
|
||||
bool rxphy_pwron;
|
||||
bool txphy_pwron;
|
||||
@@ -118,7 +117,6 @@ struct rk628_csi {
|
||||
bool continues_clk;
|
||||
bool cec_enable;
|
||||
struct rk628_hdmirx_cec *cec;
|
||||
bool is_dvi;
|
||||
struct rk628_hdcp hdcp;
|
||||
bool i2s_enable_default;
|
||||
HAUDINFO audio_info;
|
||||
@@ -731,11 +729,9 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
|
||||
{
|
||||
u8 video_fmt;
|
||||
u32 val;
|
||||
int avi_rdy;
|
||||
|
||||
mutex_lock(&csi->confctl_mutex);
|
||||
csi->avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
|
||||
mutex_unlock(&csi->confctl_mutex);
|
||||
|
||||
avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
|
||||
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
video_fmt = (val & VIDEO_FORMAT_MASK) >> 5;
|
||||
v4l2_info(&csi->sd, "%s PDEC_AVI_PB:%#x, video format:%d\n",
|
||||
@@ -762,7 +758,7 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
|
||||
}
|
||||
|
||||
/* if avi packet is not stable, reset ctrl*/
|
||||
if (!csi->avi_rdy) {
|
||||
if (!avi_rdy) {
|
||||
csi->nosignal = true;
|
||||
schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20);
|
||||
}
|
||||
@@ -930,6 +926,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
|
||||
u8 lanes = csi->csi_lanes_in_use;
|
||||
u8 lane_num;
|
||||
u32 wc_usrdef, val;
|
||||
int avi_rdy;
|
||||
|
||||
lane_num = lanes - 1;
|
||||
csi->rk628->dphy_lane_en = (1 << (lanes + 1)) - 1;
|
||||
@@ -1086,9 +1083,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
|
||||
v4l2_dbg(1, debug, sd, "%s csi1 config done\n", __func__);
|
||||
}
|
||||
|
||||
mutex_lock(&csi->confctl_mutex);
|
||||
csi->avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
|
||||
mutex_unlock(&csi->confctl_mutex);
|
||||
avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
|
||||
|
||||
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
video_fmt = (val & VIDEO_FORMAT_MASK) >> 5;
|
||||
@@ -1111,7 +1106,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
|
||||
rk628_post_process_csc_en(csi->rk628);
|
||||
}
|
||||
/* if avi packet is not stable, reset ctrl*/
|
||||
if (!csi->avi_rdy) {
|
||||
if (!avi_rdy) {
|
||||
csi->nosignal = true;
|
||||
schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20);
|
||||
}
|
||||
@@ -1252,12 +1247,8 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd)
|
||||
__func__, width, height, frame_width, frame_height, status, cnt);
|
||||
|
||||
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_STS, &val);
|
||||
if (csi->rk628->version < RK628F_VERSION && (val & DVI_DET)) {
|
||||
csi->is_dvi = true;
|
||||
if (csi->rk628->version < RK628F_VERSION && (val & DVI_DET))
|
||||
dev_info(csi->dev, "DVI mode detected\n");
|
||||
} else {
|
||||
csi->is_dvi = false;
|
||||
}
|
||||
|
||||
if (!tx_5v_power_present(sd)) {
|
||||
v4l2_info(sd, "HDMI pull out, return!\n");
|
||||
@@ -2188,6 +2179,7 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
long ret = 0;
|
||||
struct rkmodule_csi_dphy_param *dphy_param;
|
||||
struct rkmodule_capture_info *capture_info;
|
||||
u32 val;
|
||||
|
||||
switch (cmd) {
|
||||
case RKMODULE_GET_MODULE_INFO:
|
||||
@@ -2234,10 +2226,11 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
*(int *)arg = rk628_hdmirx_get_hdcp_enc_status(csi->rk628);
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_INPUT_MODE:
|
||||
*(int *)arg = csi->is_dvi;
|
||||
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_STS, &val);
|
||||
*(int *)arg = val & DVI_DET;
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS:
|
||||
*(int *)arg = csi->avi_rdy;
|
||||
*(int *)arg = !csi->nosignal;
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_SCAN_MODE:
|
||||
if (csi->timings.bt.interlaced == V4L2_DV_INTERLACED)
|
||||
@@ -2253,6 +2246,9 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
case RK_HDMIRX_CMD_GET_COLOR_RANGE:
|
||||
*(int *)arg = rk628_hdmirx_get_range(csi->rk628);
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_COLOR_SPACE:
|
||||
*(int *)arg = rk628_hdmirx_get_color_space(csi->rk628);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -2537,6 +2533,20 @@ static long rk628_csi_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
}
|
||||
kfree(seq);
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_COLOR_SPACE:
|
||||
seq = kzalloc(sizeof(*seq), GFP_KERNEL);
|
||||
if (!seq) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
ret = rk628_csi_ioctl(sd, cmd, seq);
|
||||
if (!ret) {
|
||||
ret = copy_to_user(up, seq, sizeof(*seq));
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
kfree(seq);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/soc/rockchip/rk_vendor_storage.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rk_hdmirx_config.h>
|
||||
|
||||
#include "rk628.h"
|
||||
#include "rk628_combrxphy.h"
|
||||
@@ -49,6 +50,30 @@ struct hdmirx_tmdsclk_cnt {
|
||||
u8 cnt;
|
||||
};
|
||||
|
||||
enum hdmirx_pix_fmt {
|
||||
HDMIRX_RGB888 = 0,
|
||||
HDMIRX_YUV422 = 1,
|
||||
HDMIRX_YUV444 = 2,
|
||||
HDMIRX_YUV420 = 3,
|
||||
};
|
||||
|
||||
static const char * const bus_format_str[] = {
|
||||
"RGB",
|
||||
"YUV422",
|
||||
"YUV444",
|
||||
"YUV420",
|
||||
"UNKNOWN",
|
||||
};
|
||||
|
||||
static const char *bus_color_range_str[3] = {
|
||||
"Default", "Limited", "Full"
|
||||
};
|
||||
|
||||
static const char *bus_color_space_str[8] = {
|
||||
"xvYCC601", "xvYCC709", "sYCC601", "Adobe_YCC601",
|
||||
"Adobe_RGB", "BT2020_YcCbcCrc", "BT2020_RGB_OR_YCbCr"
|
||||
};
|
||||
|
||||
#define HDMIRX_GET_TMDSCLK_TIME 21
|
||||
|
||||
static int supported_fs[] = {
|
||||
@@ -1185,14 +1210,6 @@ void rk628_hdmirx_phy_prepclk_cfg(struct rk628 *rk628)
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_phy_prepclk_cfg);
|
||||
|
||||
static const char * const bus_format_str[] = {
|
||||
"RGB",
|
||||
"YUV422",
|
||||
"YUV444",
|
||||
"YUV420",
|
||||
"UNKNOWN",
|
||||
};
|
||||
|
||||
u8 rk628_hdmirx_get_format(struct rk628 *rk628)
|
||||
{
|
||||
u32 val;
|
||||
@@ -1280,7 +1297,7 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
u32 hofs_pix, hbp, hfp, vbp, vfp;
|
||||
u32 tmds_clk, tmdsclk_cnt;
|
||||
u64 tmp_data;
|
||||
u8 video_fmt;
|
||||
u8 video_fmt, vic, color_range, color_space;
|
||||
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
timings->type = V4L2_DV_BT_656_1120;
|
||||
@@ -1341,7 +1358,11 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
hfp = htotal - hact - hofs_pix;
|
||||
vfp = vtotal - vact - vs - vbp;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
vic = (val & VID_IDENT_CODE_MASK) >> 24;
|
||||
video_fmt = rk628_hdmirx_get_format(rk628);
|
||||
color_range = rk628_hdmirx_get_range(rk628);
|
||||
color_space = rk628_hdmirx_get_color_space(rk628);
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
htotal *= 2;
|
||||
hact *= 2;
|
||||
@@ -1352,6 +1373,8 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
|
||||
dev_info(rk628->dev, "cnt_num:%d, tmds_cnt:%d, hs_cnt:%d, vs_cnt:%d, hofs:%d\n",
|
||||
HDMIRX_MODETCLK_CNT_NUM, tmdsclk_cnt, modetclk_cnt_hs, modetclk_cnt_vs, hofs_pix);
|
||||
dev_info(rk628->dev, "get current aviif: vic:%d, color_range: %s, color_space %s",
|
||||
vic, bus_color_range_str[color_range], bus_color_space_str[color_space]);
|
||||
|
||||
bt->width = hact;
|
||||
bt->height = vact;
|
||||
@@ -1490,20 +1513,57 @@ EXPORT_SYMBOL(rk628_hdmirx_get_timings);
|
||||
|
||||
u8 rk628_hdmirx_get_range(struct rk628 *rk628)
|
||||
{
|
||||
u32 val;
|
||||
u8 color_range;
|
||||
u32 val, vic, fmt;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
color_range = (val & RGB_COLORRANGE_MASK) >> 18;
|
||||
if (color_range == 0x1)
|
||||
color_range = CSC_LIMIT_RANGE;
|
||||
else
|
||||
color_range = CSC_FULL_RANGE;
|
||||
vic = (val & VID_IDENT_CODE_MASK) >> 24;
|
||||
fmt = (val & VIDEO_FORMAT_MASK) >> 5;
|
||||
if (fmt == HDMIRX_RGB888 && color_range == HDMIRX_DEFAULT_RANGE) {
|
||||
(vic) ?
|
||||
(color_range = HDMIRX_LIMIT_RANGE) :
|
||||
(color_range = HDMIRX_FULL_RANGE);
|
||||
}
|
||||
|
||||
return color_range;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_range);
|
||||
|
||||
u8 rk628_hdmirx_get_color_space(struct rk628 *rk628)
|
||||
{
|
||||
u32 val, EC2_0, C1_C0, fmt;
|
||||
u8 color_space;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
EC2_0 = (val & EXT_COLORIMETRY_MASK) >> 20;
|
||||
C1_C0 = (val & COLORIMETRY_MASK) >> 14;
|
||||
fmt = (val & VIDEO_FORMAT_MASK) >> 5;
|
||||
if (fmt == HDMIRX_RGB888) {
|
||||
(C1_C0 == 0) ?
|
||||
(color_space = HDMIRX_RGB) :
|
||||
(color_space = EC2_0);
|
||||
} else {
|
||||
switch (C1_C0) {
|
||||
case 0:
|
||||
color_space = HDMIRX_XVYCC709;
|
||||
break;
|
||||
case 1:
|
||||
color_space = HDMIRX_XVYCC601;
|
||||
break;
|
||||
case 2:
|
||||
color_space = HDMIRX_XVYCC709;
|
||||
break;
|
||||
default:
|
||||
color_space = EC2_0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return color_space;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_color_space);
|
||||
|
||||
void rk628_hdmirx_controller_reset(struct rk628 *rk628)
|
||||
{
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
|
||||
@@ -255,7 +255,12 @@
|
||||
#define DVI_DET BIT(28)
|
||||
#define HDMI_RX_PDEC_GCP_AVMUTE (HDMI_RX_BASE + 0x0380)
|
||||
#define PKTDEC_GCP_CD_MASK GENMASK(7, 4)
|
||||
#define HDMI_RX_PDEC_AVI_HB (HDMI_RX_BASE + 0x03a0)
|
||||
#define HDMI_RX_PDEC_AVI_PB (HDMI_RX_BASE + 0x03a4)
|
||||
#define VID_IDENT_CODE_VIC7 BIT(31)
|
||||
#define VID_IDENT_CODE_MASK GENMASK(30, 24)
|
||||
#define EXT_COLORIMETRY_MASK GENMASK(22, 20)
|
||||
#define COLORIMETRY_MASK GENMASK(15, 14)
|
||||
#define VIDEO_FORMAT_MASK GENMASK(6, 5)
|
||||
#define VIDEO_FORMAT(x) UPDATE(x, 6, 5)
|
||||
#define RGB_COLORRANGE_MASK GENMASK(19, 18)
|
||||
@@ -517,6 +522,7 @@ u32 rk628_hdmirx_get_tmdsclk_cnt(struct rk628 *rk628);
|
||||
int rk628_hdmirx_get_timings(struct rk628 *rk628,
|
||||
struct v4l2_dv_timings *timings);
|
||||
u8 rk628_hdmirx_get_range(struct rk628 *rk628);
|
||||
u8 rk628_hdmirx_get_color_space(struct rk628 *rk628);
|
||||
int rk628_hdmirx_get_hdcp_enc_status(struct rk628 *rk628);
|
||||
void rk628_hdmirx_controller_reset(struct rk628 *rk628);
|
||||
bool rk628_hdmirx_scdc_ced_err(struct rk628 *rk628);
|
||||
|
||||
@@ -42,6 +42,7 @@ enum hdmirx_color_space {
|
||||
HDMIRX_ADOBE_RGB = 4,
|
||||
HDMIRX_BT2020_YCC_CONST_LUM = 5,
|
||||
HDMIRX_BT2020_RGB_OR_YCC = 6,
|
||||
HDMIRX_RGB = 7,
|
||||
};
|
||||
|
||||
/* hdmirx scan mode */
|
||||
|
||||
Reference in New Issue
Block a user