Merge commit '2ee64657c086046c4d6eb78376e163a158a8a5b7'

* commit '2ee64657c086046c4d6eb78376e163a158a8a5b7':
  media: i2c: rk628: implement RK_HDMIRX_V4L2_EVENT_AUDIOINFO event
  arm64: dts: rockchip: rk3576-evb1-v10-rk628-hdmi2csi: use rockchip hdmi as rk628 hdmiin sound
  media: i2c: rk628: register a codec for hdmirx audio
  media: i2c: rk628: only disable i2s data out only when disabling i2s out
  arm64: dts: rockchip: rk3576-evb: add edp sound support
  arm64: dts: rockchip: rk3576: add property #sound-dai-cells for edp
  drm/rockchip: analogix_dp: fix the max_i2s_channels to 8
  input: touchscreen: fix build error with CONFIG_FB
  media: i2c: rk628: fix background not be disabled
  media: i2c: rk628: fix problem of loop pulling down and up cec hpd
  soc: rockchip: csu: Implement rockchip_csu_get_bus()
  media: i2c: rk628: add workaround for HDMI ARC
  media: i2c: rk628: add attributes for enabling HDMI ARC
  video: rockchip: mpp: add vdpu383 int_err_mask
  drm/rockchip: dw_hdmi: Fix some TVS all resolutions are filtered
  arm64: dts: rockchip: rk3576: reduce DS of pwm0/pwm2 pins to level2
  drm/rockchip: dsi2: enable hs clk once the init cmds be sent by default

Change-Id: If20e80d5b0b9d91304454747beafbaffb81b0e8b
This commit is contained in:
Tao Huang
2024-05-16 19:37:19 +08:00
17 changed files with 637 additions and 246 deletions

View File

@@ -116,6 +116,15 @@
rockchip,jack-det;
};
edp_sound: edp-sound {
status = "disabled";
compatible = "rockchip,hdmi";
rockchip,mclk-fs = <128>;
rockchip,card-name = "rockchip-edp";
rockchip,cpu = <&sai6>;
rockchip,codec = <&edp 0>;
};
hdmi_sound: hdmi-sound {
compatible = "rockchip,hdmi";
rockchip,mclk-fs = <128>;

View File

@@ -23,19 +23,16 @@
status = "okay";
};
hdmiin-sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "rockchip,hdmiin";
simple-audio-card,bitclock-master = <&dailink0_master>;
simple-audio-card,frame-master = <&dailink0_master>;
hdmiin_sound: hdmiin-sound {
status = "okay";
simple-audio-card,cpu {
sound-dai = <&sai4>;
};
dailink0_master: simple-audio-card,codec {
sound-dai = <&rk628_dc>;
};
compatible = "rockchip,hdmi";
rockchip,mclk-fs = <128>;
rockchip,card-name = "rockchip,rk628hdmiin";
rockchip,cpu = <&sai4>;
rockchip,codec = <&rk628_csi>;
rockchip,bitclock-master = <&rk628_csi>;
rockchip,frame-master = <&rk628_csi>;
rockchip,jack-det;
};
};
@@ -96,6 +93,7 @@
plugin-det-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_LOW>;
continues-clk = <1>;
cec-enable;
#sound-dai-cells = <0>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
@@ -174,6 +172,7 @@
pinctrl-0 = <&sai4m2_lrck
&sai4m2_sclk
&sai4m2_sdi>;
rockchip,sai-rx-wait-time-ms = <50>;
status = "okay";
};

View File

@@ -2541,56 +2541,56 @@
pwm0m0_ch0: pwm0m0-ch0 {
rockchip,pins =
/* pwm0_ch0_m0 */
<0 RK_PC4 12 &pcfg_pull_none>;
<0 RK_PC4 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m0_ch1: pwm0m0-ch1 {
rockchip,pins =
/* pwm0_ch1_m0 */
<0 RK_PC3 12 &pcfg_pull_none>;
<0 RK_PC3 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m1_ch0: pwm0m1-ch0 {
rockchip,pins =
/* pwm0_ch0_m1 */
<1 RK_PC0 13 &pcfg_pull_none>;
<1 RK_PC0 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m1_ch1: pwm0m1-ch1 {
rockchip,pins =
/* pwm0_ch1_m1 */
<4 RK_PC1 14 &pcfg_pull_none>;
<4 RK_PC1 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m2_ch0: pwm0m2-ch0 {
rockchip,pins =
/* pwm0_ch0_m2 */
<2 RK_PC3 13 &pcfg_pull_none>;
<2 RK_PC3 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m2_ch1: pwm0m2-ch1 {
rockchip,pins =
/* pwm0_ch1_m2 */
<2 RK_PC7 13 &pcfg_pull_none>;
<2 RK_PC7 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m3_ch0: pwm0m3-ch0 {
rockchip,pins =
/* pwm0_ch0_m3 */
<3 RK_PB0 12 &pcfg_pull_none>;
<3 RK_PB0 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm0m3_ch1: pwm0m3-ch1 {
rockchip,pins =
/* pwm0_ch1_m3 */
<3 RK_PB6 12 &pcfg_pull_none>;
<3 RK_PB6 12 &pcfg_pull_none_drv_level_2>;
};
};
@@ -2769,224 +2769,224 @@
pwm2m0_ch0: pwm2m0-ch0 {
rockchip,pins =
/* pwm2_ch0_m0 */
<0 RK_PD3 12 &pcfg_pull_none>;
<0 RK_PD3 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch1: pwm2m0-ch1 {
rockchip,pins =
/* pwm2_ch1_m0 */
<1 RK_PB3 12 &pcfg_pull_none>;
<1 RK_PB3 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch2: pwm2m0-ch2 {
rockchip,pins =
/* pwm2_ch2_m0 */
<2 RK_PA0 14 &pcfg_pull_none>;
<2 RK_PA0 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch3: pwm2m0-ch3 {
rockchip,pins =
/* pwm2_ch3_m0 */
<2 RK_PA1 14 &pcfg_pull_none>;
<2 RK_PA1 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch4: pwm2m0-ch4 {
rockchip,pins =
/* pwm2_ch4_m0 */
<2 RK_PA4 14 &pcfg_pull_none>;
<2 RK_PA4 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch5: pwm2m0-ch5 {
rockchip,pins =
/* pwm2_ch5_m0 */
<4 RK_PA2 13 &pcfg_pull_none>;
<4 RK_PA2 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch6: pwm2m0-ch6 {
rockchip,pins =
/* pwm2_ch6_m0 */
<4 RK_PA7 13 &pcfg_pull_none>;
<4 RK_PA7 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m0_ch7: pwm2m0-ch7 {
rockchip,pins =
/* pwm2_ch7_m0 */
<4 RK_PB3 13 &pcfg_pull_none>;
<4 RK_PB3 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch0: pwm2m1-ch0 {
rockchip,pins =
/* pwm2_ch0_m1 */
<4 RK_PC2 14 &pcfg_pull_none>;
<4 RK_PC2 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch1: pwm2m1-ch1 {
rockchip,pins =
/* pwm2_ch1_m1 */
<4 RK_PC3 14 &pcfg_pull_none>;
<4 RK_PC3 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch2: pwm2m1-ch2 {
rockchip,pins =
/* pwm2_ch2_m1 */
<4 RK_PC6 14 &pcfg_pull_none>;
<4 RK_PC6 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch3: pwm2m1-ch3 {
rockchip,pins =
/* pwm2_ch3_m1 */
<4 RK_PC7 14 &pcfg_pull_none>;
<4 RK_PC7 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch4: pwm2m1-ch4 {
rockchip,pins =
/* pwm2_ch4_m1 */
<4 RK_PA3 13 &pcfg_pull_none>;
<4 RK_PA3 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch5: pwm2m1-ch5 {
rockchip,pins =
/* pwm2_ch5_m1 */
<4 RK_PC5 14 &pcfg_pull_none>;
<4 RK_PC5 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch6: pwm2m1-ch6 {
rockchip,pins =
/* pwm2_ch6_m1 */
<4 RK_PC4 14 &pcfg_pull_none>;
<4 RK_PC4 14 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m1_ch7: pwm2m1-ch7 {
rockchip,pins =
/* pwm2_ch7_m1 */
<1 RK_PB1 12 &pcfg_pull_none>;
<1 RK_PB1 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch0: pwm2m2-ch0 {
rockchip,pins =
/* pwm2_ch0_m2 */
<2 RK_PD0 13 &pcfg_pull_none>;
<2 RK_PD0 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch1: pwm2m2-ch1 {
rockchip,pins =
/* pwm2_ch1_m2 */
<2 RK_PD1 13 &pcfg_pull_none>;
<2 RK_PD1 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch2: pwm2m2-ch2 {
rockchip,pins =
/* pwm2_ch2_m2 */
<2 RK_PD2 13 &pcfg_pull_none>;
<2 RK_PD2 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch3: pwm2m2-ch3 {
rockchip,pins =
/* pwm2_ch3_m2 */
<2 RK_PD3 13 &pcfg_pull_none>;
<2 RK_PD3 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch4: pwm2m2-ch4 {
rockchip,pins =
/* pwm2_ch4_m2 */
<2 RK_PD4 13 &pcfg_pull_none>;
<2 RK_PD4 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch5: pwm2m2-ch5 {
rockchip,pins =
/* pwm2_ch5_m2 */
<2 RK_PD5 13 &pcfg_pull_none>;
<2 RK_PD5 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch6: pwm2m2-ch6 {
rockchip,pins =
/* pwm2_ch6_m2 */
<2 RK_PD6 13 &pcfg_pull_none>;
<2 RK_PD6 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m2_ch7: pwm2m2-ch7 {
rockchip,pins =
/* pwm2_ch7_m2 */
<2 RK_PD7 13 &pcfg_pull_none>;
<2 RK_PD7 13 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch0: pwm2m3-ch0 {
rockchip,pins =
/* pwm2_ch0_m3 */
<3 RK_PC2 12 &pcfg_pull_none>;
<3 RK_PC2 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch1: pwm2m3-ch1 {
rockchip,pins =
/* pwm2_ch1_m3 */
<3 RK_PC3 12 &pcfg_pull_none>;
<3 RK_PC3 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch2: pwm2m3-ch2 {
rockchip,pins =
/* pwm2_ch2_m3 */
<3 RK_PC5 12 &pcfg_pull_none>;
<3 RK_PC5 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch3: pwm2m3-ch3 {
rockchip,pins =
/* pwm2_ch3_m3 */
<3 RK_PD0 12 &pcfg_pull_none>;
<3 RK_PD0 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch4: pwm2m3-ch4 {
rockchip,pins =
/* pwm2_ch4_m3 */
<3 RK_PD2 12 &pcfg_pull_none>;
<3 RK_PD2 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch5: pwm2m3-ch5 {
rockchip,pins =
/* pwm2_ch5_m3 */
<3 RK_PD3 12 &pcfg_pull_none>;
<3 RK_PD3 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch6: pwm2m3-ch6 {
rockchip,pins =
/* pwm2_ch6_m3 */
<3 RK_PD6 12 &pcfg_pull_none>;
<3 RK_PD6 12 &pcfg_pull_none_drv_level_2>;
};
/omit-if-no-ref/
pwm2m3_ch7: pwm2m3-ch7 {
rockchip,pins =
/* pwm2_ch7_m3 */
<3 RK_PD7 12 &pcfg_pull_none>;
<3 RK_PD7 12 &pcfg_pull_none_drv_level_2>;
};
};

View File

@@ -3158,6 +3158,7 @@
phy-names = "dp";
power-domains = <&power RK3576_PD_VO0>;
rockchip,grf = <&vo0_grf>;
#sound-dai-cells = <1>;
status = "disabled";
ports {

View File

@@ -600,7 +600,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
.ops = &rockchip_dp_audio_codec_ops,
.spdif = 1,
.i2s = 1,
.max_i2s_channels = 2,
.max_i2s_channels = 8,
};
dp->audio_pdev =

View File

@@ -243,7 +243,6 @@ struct dw_mipi_dsi2 {
struct clk *pclk;
struct clk *sys_clk;
bool phy_enabled;
bool phy_request_clkhs;
struct phy *dcphy;
union phy_configure_opts phy_opts;
@@ -832,10 +831,9 @@ static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2)
dw_mipi_dsi2_pre_enable(dsi2->slave);
}
static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2)
static void dw_mipi_dsi2_clk_management(struct dw_mipi_dsi2 *dsi2)
{
u32 clk_type, mode;
int ret;
u32 clk_type;
/*
* initial deskew calibration is send after phy_power_on,
@@ -848,7 +846,14 @@ static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2)
regmap_update_bits(dsi2->regmap, DSI2_PHY_CLK_CFG,
CLK_TYPE_MASK, clk_type);
}
static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2)
{
u32 mode;
int ret;
dw_mipi_dsi2_clk_management(dsi2);
dw_mipi_dsi2_ipi_set(dsi2);
if (dsi2->auto_calc_mode) {
@@ -1633,18 +1638,9 @@ static ssize_t dw_mipi_dsi2_transfer(struct dw_mipi_dsi2 *dsi2,
u32 val;
u32 mode;
if (msg->flags & MIPI_DSI_MSG_USE_LPM) {
regmap_update_bits(dsi2->regmap, DSI2_PHY_CLK_CFG,
CLK_TYPE_MASK, dsi2->phy_request_clkhs ?
CONTIUOUS_CLK : NON_CONTINUOUS_CLK);
regmap_update_bits(dsi2->regmap, DSI2_DSI_VID_TX_CFG,
LPDT_DISPLAY_CMD_EN, LPDT_DISPLAY_CMD_EN);
} else {
regmap_update_bits(dsi2->regmap, DSI2_PHY_CLK_CFG,
CLK_TYPE_MASK, CONTIUOUS_CLK);
regmap_update_bits(dsi2->regmap, DSI2_DSI_VID_TX_CFG,
LPDT_DISPLAY_CMD_EN, 0);
}
dw_mipi_dsi2_clk_management(dsi2);
regmap_update_bits(dsi2->regmap, DSI2_DSI_VID_TX_CFG, LPDT_DISPLAY_CMD_EN,
msg->flags & MIPI_DSI_MSG_USE_LPM ? LPDT_DISPLAY_CMD_EN : 0);
/* create a packet to the DSI protocol */
ret = mipi_dsi_create_packet(&packet, msg);
@@ -1732,9 +1728,6 @@ static int dw_mipi_dsi2_probe(struct platform_device *pdev)
dsi2->pdata = of_device_get_match_data(dev);
platform_set_drvdata(pdev, dsi2);
if (device_property_read_bool(dev, "phy-request-clkhs"))
dsi2->phy_request_clkhs = true;
if (device_property_read_bool(dev, "auto-calculation-mode"))
dsi2->auto_calc_mode = true;

View File

@@ -1830,8 +1830,14 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
hdmi = to_rockchip_hdmi(encoder);
if (!hdmi->skip_check_420_mode) {
u32 max_tmds_clock = connector->display_info.max_tmds_clock;
/* some sinks edid max_tmds_clocks are 0, we think it only support hdmi1.4 */
if (!connector->display_info.max_tmds_clock)
max_tmds_clock = 340000;
/* edid isn't support yuv420 and max_tmds_clock is less than mode pixel clk */
if (mode->clock < 600000 && connector->display_info.max_tmds_clock < mode->clock &&
if (mode->clock < 600000 && max_tmds_clock < mode->clock &&
(!drm_mode_is_420(&connector->display_info, mode) ||
!connector->ycbcr_420_allowed))
return MODE_BAD;
@@ -1846,7 +1852,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
* exceeds the max_tmds_clock of edid.
*/
if (drm_mode_is_420(&connector->display_info, mode) &&
connector->display_info.max_tmds_clock < (mode->clock / 2) &&
max_tmds_clock < (mode->clock / 2) &&
is_hdmi2_mode(mode))
return MODE_BAD;
};

View File

@@ -1432,7 +1432,7 @@ static void fts_resume_work(struct work_struct *work)
}
#if defined(CONFIG_FB)
static int fb_notifier_callback(struct notifier_block *self,
static int fts_fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct fb_event *evdata = data;
@@ -1445,7 +1445,7 @@ static int fb_notifier_callback(struct notifier_block *self,
return 0;
}
if (!(event == FB_EARLY_EVENT_BLANK || event == FB_EVENT_BLANK)) {
if (event != FB_EVENT_BLANK) {
FTS_INFO("event(%lu) do not need process\n", event);
return 0;
}
@@ -1454,18 +1454,14 @@ static int fb_notifier_callback(struct notifier_block *self,
FTS_INFO("FB event:%lu,blank:%d", event, *blank);
switch (*blank) {
case FB_BLANK_UNBLANK:
if (FB_EARLY_EVENT_BLANK == event) {
FTS_INFO("resume: event = %lu, not care\n", event);
} else if (FB_EVENT_BLANK == event) {
if (FB_EVENT_BLANK == event) {
queue_work(fts_data->ts_workqueue, &fts_data->resume_work);
}
break;
case FB_BLANK_POWERDOWN:
if (FB_EARLY_EVENT_BLANK == event) {
if (FB_EVENT_BLANK == event) {
cancel_work_sync(&fts_data->resume_work);
fts_ts_suspend(ts_data->dev);
} else if (FB_EVENT_BLANK == event) {
FTS_INFO("suspend: event = %lu, not care\n", event);
}
break;
default:
@@ -1766,7 +1762,7 @@ static int fts_ts_probe_entry(struct fts_ts_data *ts_data)
#endif
#if defined(CONFIG_FB)
ts_data->fb_notif.notifier_call = fb_notifier_callback;
ts_data->fb_notif.notifier_call = fts_fb_notifier_callback;
ret = fb_register_client(&ts_data->fb_notif);
if (ret) {
FTS_ERROR("[FB]Unable to register fb_notifier: %d", ret);

View File

@@ -12305,7 +12305,7 @@ static void pt_setup_early_suspend(struct pt_core_data *cd)
}
#elif defined(CONFIG_FB)
/*******************************************************************************
* FUNCTION: fb_notifier_callback
* FUNCTION: pt_fb_notifier_callback
*
* SUMMARY: Call back function for FrameBuffer notifier to allow to call
* resume/suspend attention list.
@@ -12318,7 +12318,7 @@ static void pt_setup_early_suspend(struct pt_core_data *cd)
* event - event type of fb notifier
* *data - pointer to fb_event structure
******************************************************************************/
static int fb_notifier_callback(struct notifier_block *self,
static int pt_fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct pt_core_data *cd =
@@ -12370,7 +12370,7 @@ static void pt_setup_fb_notifier(struct pt_core_data *cd)
cd->fb_state = FB_ON;
cd->fb_notifier.notifier_call = fb_notifier_callback;
cd->fb_notifier.notifier_call = pt_fb_notifier_callback;
rc = fb_register_client(&cd->fb_notifier);
if (rc)

View File

@@ -251,7 +251,7 @@ static bool tx_5v_power_present(struct v4l2_subdev *sd)
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
ret = rk628_hdmirx_tx_5v_power_detect(bt1120->plugin_det_gpio);
v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret);
v4l2_dbg(2, debug, sd, "%s: %d\n", __func__, ret);
return ret;
}
@@ -464,6 +464,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
bool plugin;
mutex_lock(&bt1120->confctl_mutex);
rk628_set_bg_enable(bt1120->rk628, false);
enable_stream(sd, false);
bt1120->nosignal = true;
bt1120->avi_rcv_rdy = false;
@@ -513,7 +514,7 @@ static void rk628_hdmirx_hpd_ctrl(struct v4l2_subdev *sd, bool en)
HOT_PLUG_DETECT_MASK, HOT_PLUG_DETECT(set_level));
if (bt1120->cec_enable && bt1120->cec)
rk628_hdmirx_cec_hpd(bt1120->cec, en);
rk628_hdmirx_cec_hpd(bt1120->cec, tx_5v_power_present(sd));
}
static int rk628_bt1120_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd)
@@ -950,16 +951,23 @@ static void rk628_bt1120_clear_hdmirx_interrupts(struct v4l2_subdev *sd)
{
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
/* clear interrupts */
rk628_i2c_write(bt1120->rk628, HDMI_RX_MD_ICLR, 0xffffffff);
rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
if (bt1120->rk628->version >= RK628F_VERSION)
rk628_i2c_write(bt1120->rk628, GRF_INTR0_CLR_EN, 0x02000200);
else
rk628_i2c_write(bt1120->rk628, GRF_INTR0_CLR_EN, 0x01000100);
}
static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
static int rk628_is_general_isr(struct rk628_bt1120 *bt1120, u32 md_ints, u32 pdec_ints)
{
if (rk628_hdmirx_is_signal_change_ists(bt1120->rk628, md_ints, pdec_ints))
return 1;
if ((pdec_ints & AVI_RCV_ISTS) && !bt1120->avi_rcv_rdy)
return 1;
return 0;
}
static int rk628_hdmirx_general_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
u32 md_ints, pdec_ints, fifo_ints, hact, vact;
@@ -972,11 +980,25 @@ static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return -EINVAL;
}
if (!bt1120->vid_ints_en)
return 0;
rk628_i2c_read(bt1120->rk628, GRF_INTR0_STATUS, &int0_status);
if (!(int0_status & (BIT(8) | BIT(9))))
return 0;
v4l2_dbg(1, debug, sd, "%s: int0 status: 0x%x\n", __func__, int0_status);
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_ISTS, &md_ints);
rk628_i2c_read(bt1120->rk628, HDMI_RX_PDEC_ISTS, &pdec_ints);
/* clear interrupts */
rk628_i2c_write(bt1120->rk628, HDMI_RX_MD_ICLR, 0xffffffff);
rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
if (!rk628_is_general_isr(bt1120, md_ints, pdec_ints))
return 0;
if (bt1120->rk628->version >= RK628F_VERSION &&
rk628_hdmirx_is_signal_change_ists(bt1120->rk628, md_ints, pdec_ints))
rk628_set_bg_enable(bt1120->rk628, true);
@@ -1003,37 +1025,34 @@ static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
}
}
}
if (bt1120->vid_ints_en) {
v4l2_dbg(1, debug, sd, "%s: md_ints: %#x, pdec_ints:%#x, plugin: %d\n",
__func__, md_ints, pdec_ints, plugin);
v4l2_dbg(1, debug, sd, "%s: md_ints: %#x, pdec_ints:%#x, plugin: %d\n",
__func__, md_ints, pdec_ints, plugin);
if (rk628_hdmirx_is_signal_change_ists(bt1120->rk628, md_ints, pdec_ints)) {
if (rk628_hdmirx_is_signal_change_ists(bt1120->rk628, md_ints, pdec_ints)) {
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HACT_PX, &hact);
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VAL, &vact);
v4l2_dbg(1, debug, sd, "%s: HACT:%#x, VACT:%#x\n",
__func__, hact, vact);
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HACT_PX, &hact);
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VAL, &vact);
v4l2_dbg(1, debug, sd, "%s: HACT:%#x, VACT:%#x\n",
__func__, hact, vact);
rk628_bt1120_enable_interrupts(sd, false);
if (bt1120->rk628->version < RK628F_VERSION) {
enable_stream(sd, false);
bt1120->nosignal = true;
}
schedule_delayed_work(&bt1120->delayed_work_res_change, HZ / 2);
v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n",
__func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS)));
*handled = true;
rk628_bt1120_enable_interrupts(sd, false);
if (bt1120->rk628->version < RK628F_VERSION) {
enable_stream(sd, false);
bt1120->nosignal = true;
}
schedule_delayed_work(&bt1120->delayed_work_res_change, HZ / 2);
if ((pdec_ints & AVI_RCV_ISTS) && plugin && !bt1120->avi_rcv_rdy) {
v4l2_dbg(1, debug, sd, "%s: AVI RCV INT!\n", __func__);
bt1120->avi_rcv_rdy = true;
/* After get the AVI_RCV interrupt state, disable interrupt. */
rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS);
v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n",
__func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS)));
*handled = true;
}
*handled = true;
}
if ((pdec_ints & AVI_RCV_ISTS) && plugin && !bt1120->avi_rcv_rdy) {
v4l2_dbg(1, debug, sd, "%s: AVI RCV INT!\n", __func__);
bt1120->avi_rcv_rdy = true;
/* After get the AVI_RCV interrupt state, disable interrupt. */
rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS);
*handled = true;
}
if (*handled != true)
v4l2_dbg(1, debug, sd, "%s: unhandled interrupt!\n", __func__);
@@ -1041,17 +1060,25 @@ static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return 0;
}
static int rk628_hdmirx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
rk628_hdmirx_general_isr(sd, status, handled);
if (bt1120->cec_enable && bt1120->cec)
rk628_hdmirx_cec_irq(bt1120->rk628, bt1120->cec);
rk628_bt1120_clear_hdmirx_interrupts(sd);
return 0;
}
static irqreturn_t rk628_bt1120_irq_handler(int irq, void *dev_id)
{
struct rk628_bt1120 *bt1120 = dev_id;
bool handled = true;
rk628_bt1120_isr(&bt1120->sd, 0, &handled);
if (bt1120->cec_enable && bt1120->cec)
rk628_hdmirx_cec_irq(bt1120->rk628, bt1120->cec);
rk628_bt1120_clear_hdmirx_interrupts(&bt1120->sd);
rk628_hdmirx_isr(&bt1120->sd, 0, &handled);
return handled ? IRQ_HANDLED : IRQ_NONE;
}
@@ -1615,7 +1642,7 @@ static const struct v4l2_subdev_internal_ops bt1120_subdev_internal_ops = {
#endif
static const struct v4l2_subdev_core_ops rk628_bt1120_core_ops = {
.interrupt_service_routine = rk628_bt1120_isr,
.interrupt_service_routine = rk628_hdmirx_isr,
.subscribe_event = rk628_bt1120_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
.ioctl = rk628_bt1120_ioctl,
@@ -2008,7 +2035,8 @@ static int rk628_bt1120_probe(struct i2c_client *client,
bt1120->audio_info = rk628_hdmirx_audioinfo_alloc(dev,
&bt1120->confctl_mutex,
rk628,
bt1120->i2s_enable_default);
bt1120->i2s_enable_default,
NULL);
if (!bt1120->audio_info) {
v4l2_err(sd, "request audio info fail\n");
goto err_work_queues;

View File

@@ -382,7 +382,7 @@ static bool tx_5v_power_present(struct v4l2_subdev *sd)
struct rk628_csi *csi = to_csi(sd);
ret = rk628_hdmirx_tx_5v_power_detect(csi->plugin_det_gpio);
v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret);
v4l2_dbg(2, debug, sd, "%s: %d\n", __func__, ret);
return ret;
}
@@ -494,6 +494,9 @@ static void rk628_hdmirx_config_all(struct v4l2_subdev *sd)
}
if (ret < 0 || rk628_hdmirx_scdc_ced_err(csi->rk628)) {
if (rk628_hdmirx_get_arc_enable(csi->audio_info))
return;
rk628_hdmirx_plugout(sd);
csi->lock_fail_time++;
v4l2_dbg(1, debug, sd, "%s: lock fail time: %d\n",
@@ -574,6 +577,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
bool plugin;
mutex_lock(&csi->confctl_mutex);
rk628_set_bg_enable(csi->rk628, false);
enable_stream(sd, false);
csi->nosignal = true;
csi->avi_rcv_rdy = false;
@@ -623,7 +627,7 @@ static void rk628_hdmirx_hpd_ctrl(struct v4l2_subdev *sd, bool en)
HOT_PLUG_DETECT_MASK, HOT_PLUG_DETECT(set_level));
if (csi->cec_enable && csi->cec)
rk628_hdmirx_cec_hpd(csi->cec, en);
rk628_hdmirx_cec_hpd(csi->cec, tx_5v_power_present(sd));
}
@@ -1571,9 +1575,6 @@ static void rk628_csi_clear_hdmirx_interrupts(struct v4l2_subdev *sd)
struct rk628_csi *csi = to_csi(sd);
v4l2_dbg(2, debug, sd, "%s: clear hdmirx ints\n", __func__);
/* clear interrupts */
rk628_i2c_write(csi->rk628, HDMI_RX_MD_ICLR, 0xffffffff);
rk628_i2c_write(csi->rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
if (csi->rk628->version >= RK628F_VERSION)
rk628_i2c_write(csi->rk628, GRF_INTR0_CLR_EN, 0x02000200);
else
@@ -1644,13 +1645,22 @@ static void rk628_csi_error_process(struct v4l2_subdev *sd)
}
}
static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
static int rk628_is_general_isr(struct rk628_csi *csi, u32 md_ints, u32 pdec_ints)
{
if (rk628_hdmirx_is_signal_change_ists(csi->rk628, md_ints, pdec_ints))
return 1;
if ((pdec_ints & AVI_RCV_ISTS) && !csi->avi_rcv_rdy)
return 1;
return 0;
}
static int rk628_hdmirx_general_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
struct rk628_csi *csi = to_csi(sd);
u32 md_ints = 0x0, pdec_ints = 0x0, fifo_ints, hact, vact;
bool plugin;
void *audio_info = csi->audio_info;
u32 csi0_raw_ints = 0x0, csi1_raw_ints = 0x0;
u32 int0_status;
const struct v4l2_event evt_signal_lost = {
.type = RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST,
@@ -1661,31 +1671,36 @@ static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return -EINVAL;
}
if (!csi->vid_ints_en)
return 0;
rk628_i2c_read(csi->rk628, GRF_INTR0_STATUS, &int0_status);
if (!(int0_status & (BIT(8) | BIT(9))))
return 0;
rk628_i2c_read(csi->rk628, HDMI_RX_MD_ISTS, &md_ints);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_ISTS, &pdec_ints);
/* clear interrupts */
rk628_i2c_write(csi->rk628, HDMI_RX_MD_ICLR, 0xffffffff);
rk628_i2c_write(csi->rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
if (!rk628_is_general_isr(csi, md_ints, pdec_ints))
return 0;
v4l2_dbg(1, debug, sd, "%s: int0 status: 0x%x\n", __func__, int0_status);
if (int0_status & (BIT(8) | BIT(9))) {
rk628_i2c_read(csi->rk628, HDMI_RX_MD_ISTS, &md_ints);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_ISTS, &pdec_ints);
if (csi->rk628->version >= RK628F_VERSION &&
rk628_hdmirx_is_signal_change_ists(csi->rk628, md_ints, pdec_ints))
rk628_set_bg_enable(csi->rk628, true);
}
if ((int0_status & (BIT(6) | BIT(7)))) {
rk628_i2c_read(csi->rk628, CSITX_ERR_INTR_RAW_STATUS_IMD, &csi0_raw_ints);
if (csi->rk628->version >= RK628F_VERSION)
rk628_i2c_read(csi->rk628, CSITX1_ERR_INTR_RAW_STATUS_IMD, &csi1_raw_ints);
rk628_csi_clear_csi_interrupts(sd);
}
if (csi->rk628->version >= RK628F_VERSION &&
rk628_hdmirx_is_signal_change_ists(csi->rk628, md_ints, pdec_ints))
rk628_set_bg_enable(csi->rk628, true);
plugin = tx_5v_power_present(sd);
if (!plugin) {
rk628_csi_enable_interrupts(sd, false);
rk628_csi_enable_csi_interrupts(sd, false);
return 0;
}
if (csi->rk628->version < RK628F_VERSION && (int0_status & BIT(8))) {
if (csi->rk628->version < RK628F_VERSION) {
if (rk628_audio_ctsnints_enabled(audio_info)) {
if (pdec_ints & (ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR)) {
rk628_csi_isr_ctsn(audio_info, pdec_ints);
@@ -1701,41 +1716,77 @@ static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
}
}
}
if (csi->vid_ints_en && (int0_status & (BIT(8) | BIT(9)))) {
v4l2_dbg(1, debug, sd, "%s: md_ints: %#x, pdec_ints:%#x, plugin: %d\n",
__func__, md_ints, pdec_ints, plugin);
if (rk628_hdmirx_is_signal_change_ists(csi->rk628, md_ints, pdec_ints)) {
rk628_i2c_read(csi->rk628, HDMI_RX_MD_HACT_PX, &hact);
rk628_i2c_read(csi->rk628, HDMI_RX_MD_VAL, &vact);
v4l2_dbg(1, debug, sd, "%s: HACT:%#x, VACT:%#x\n",
__func__, hact, vact);
v4l2_dbg(1, debug, sd, "%s: md_ints: %#x, pdec_ints:%#x, plugin: %d\n",
__func__, md_ints, pdec_ints, plugin);
rk628_csi_enable_interrupts(sd, false);
if (csi->rk628->version < RK628F_VERSION) {
enable_stream(sd, false);
csi->nosignal = true;
}
v4l2_event_queue(sd->devnode, &evt_signal_lost);
schedule_delayed_work(&csi->delayed_work_res_change, msecs_to_jiffies(100));
if (rk628_hdmirx_is_signal_change_ists(csi->rk628, md_ints, pdec_ints)) {
rk628_i2c_read(csi->rk628, HDMI_RX_MD_HACT_PX, &hact);
rk628_i2c_read(csi->rk628, HDMI_RX_MD_VAL, &vact);
v4l2_dbg(1, debug, sd, "%s: HACT:%#x, VACT:%#x\n",
__func__, hact, vact);
v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n",
__func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS)));
*handled = true;
rk628_csi_enable_interrupts(sd, false);
if (csi->rk628->version < RK628F_VERSION) {
enable_stream(sd, false);
csi->nosignal = true;
}
v4l2_event_queue(sd->devnode, &evt_signal_lost);
schedule_delayed_work(&csi->delayed_work_res_change, msecs_to_jiffies(100));
if ((pdec_ints & AVI_RCV_ISTS) && plugin && !csi->avi_rcv_rdy) {
v4l2_dbg(1, debug, sd, "%s: AVI RCV INT!\n", __func__);
if (csi->plat_data->tx_mode == DSI_MODE)
enable_stream(sd, false);
csi->avi_rcv_rdy = true;
/* After get the AVI_RCV interrupt state, disable interrupt. */
rk628_i2c_write(csi->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS);
*handled = true;
}
v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n",
__func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS)));
*handled = true;
}
if ((pdec_ints & AVI_RCV_ISTS) && plugin && !csi->avi_rcv_rdy) {
v4l2_dbg(1, debug, sd, "%s: AVI RCV INT!\n", __func__);
if (csi->plat_data->tx_mode == DSI_MODE)
enable_stream(sd, false);
csi->avi_rcv_rdy = true;
/* After get the AVI_RCV interrupt state, disable interrupt. */
rk628_i2c_write(csi->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS);
*handled = true;
}
if (*handled != true)
v4l2_dbg(1, debug, sd, "%s: unhandled interrupt!\n", __func__);
return 0;
}
static int rk628_hdmirx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
struct rk628_csi *csi = to_csi(sd);
rk628_hdmirx_general_isr(sd, status, handled);
if (csi->cec_enable && csi->cec)
rk628_hdmirx_cec_irq(csi->rk628, csi->cec);
rk628_csi_clear_hdmirx_interrupts(sd);
return 0;
}
static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
struct rk628_csi *csi = to_csi(sd);
u32 int0_status;
u32 csi0_raw_ints = 0x0, csi1_raw_ints = 0x0;
rk628_i2c_read(csi->rk628, GRF_INTR0_STATUS, &int0_status);
if (!(int0_status & (BIT(6) | BIT(7))))
return 0;
v4l2_dbg(1, debug, sd, "%s: int0 status: 0x%x\n", __func__, int0_status);
rk628_i2c_read(csi->rk628, CSITX_ERR_INTR_RAW_STATUS_IMD, &csi0_raw_ints);
if (csi->rk628->version >= RK628F_VERSION)
rk628_i2c_read(csi->rk628, CSITX1_ERR_INTR_RAW_STATUS_IMD, &csi1_raw_ints);
rk628_csi_clear_csi_interrupts(sd);
if (csi0_raw_ints || csi1_raw_ints) {
v4l2_info(sd,
"%s: csi interrupt: csi0_raw_ints: 0x%x, csi1_raw_ints: 0x%x!\n",
@@ -1750,17 +1801,20 @@ static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
return 0;
}
static int rk628_isr_process(struct v4l2_subdev *sd, u32 status, bool *handled)
{
rk628_hdmirx_isr(sd, status, handled);
rk628_csi_isr(sd, status, handled);
return 0;
}
static irqreturn_t rk628_csi_irq_handler(int irq, void *dev_id)
{
struct rk628_csi *csi = dev_id;
bool handled = true;
rk628_csi_isr(&csi->sd, 0, &handled);
if (csi->cec_enable && csi->cec)
rk628_hdmirx_cec_irq(csi->rk628, csi->cec);
rk628_csi_clear_hdmirx_interrupts(&csi->sd);
rk628_isr_process(&csi->sd, 0, &handled);
return handled ? IRQ_HANDLED : IRQ_NONE;
}
@@ -1792,6 +1846,8 @@ static int rk628_csi_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
case RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST:
return v4l2_event_subscribe(fh, sub, 0, NULL);
case RK_HDMIRX_V4L2_EVENT_AUDIOINFO:
return v4l2_event_subscribe(fh, sub, 0, NULL);
default:
return -EINVAL;
}
@@ -2786,7 +2842,7 @@ static long rk628_csi_compat_ioctl32(struct v4l2_subdev *sd,
#endif
static const struct v4l2_subdev_core_ops rk628_csi_core_ops = {
.interrupt_service_routine = rk628_csi_isr,
.interrupt_service_routine = rk628_isr_process,
.subscribe_event = rk628_csi_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
.ioctl = rk628_csi_ioctl,
@@ -2886,6 +2942,17 @@ static irqreturn_t plugin_detect_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
static void rk628_csi_audio_info_cb(struct rk628 *rk628, bool on)
{
struct i2c_client *client = to_i2c_client(rk628->dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
const struct v4l2_event evt_audio_info = {
.type = RK_HDMIRX_V4L2_EVENT_AUDIOINFO,
};
v4l2_event_queue(sd->devnode, &evt_audio_info);
}
static int rk628_csi_power_on(struct rk628_csi *csi)
{
clk_prepare_enable(csi->soc_24M);
@@ -3132,12 +3199,48 @@ static ssize_t audio_present_show(struct device *dev,
rk628_hdmirx_audio_present(csi->audio_info) : 0);
}
static ssize_t arc_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rk628_csi *csi = dev_get_drvdata(dev);
struct rk_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev);
if (!hdmirx_dev)
return -EINVAL;
return snprintf(buf, PAGE_SIZE, "%d\n",
rk628_hdmirx_get_arc_enable(csi->audio_info) ? 1 : 0);
}
static ssize_t arc_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct rk628_csi *csi = dev_get_drvdata(dev);
struct rk_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev);
bool enabled;
int ret;
if (!hdmirx_dev)
return -EINVAL;
ret = kstrtobool(buf, &enabled);
if (ret)
return ret;
rk628_hdmirx_set_arc_enable(csi->audio_info, enabled);
return count;
}
static DEVICE_ATTR_RO(audio_rate);
static DEVICE_ATTR_RO(audio_present);
static DEVICE_ATTR_RW(arc_enable);
static struct attribute *rk628_attrs[] = {
&dev_attr_audio_rate.attr,
&dev_attr_audio_present.attr,
&dev_attr_arc_enable.attr,
NULL
};
ATTRIBUTE_GROUPS(rk628);
@@ -3372,7 +3475,8 @@ static int rk628_csi_probe(struct i2c_client *client,
csi->audio_info = rk628_hdmirx_audioinfo_alloc(dev,
&csi->confctl_mutex,
rk628,
csi->i2s_enable_default);
csi->i2s_enable_default,
rk628_csi_audio_info_cb);
if (!csi->audio_info) {
err = -ENOMEM;
v4l2_err(sd, "request audio info fail\n");

View File

@@ -11,6 +11,7 @@
#include <linux/soc/rockchip/rk_vendor_storage.h>
#include <linux/slab.h>
#include <linux/rk_hdmirx_config.h>
#include <sound/hdmi-codec.h>
#include "rk628.h"
#include "rk628_combrxphy.h"
@@ -19,6 +20,8 @@
#define INIT_FIFO_STATE 64
#define DEFAULT_AUDIO_CLK 5644800
struct rk628_audiostate {
u32 hdmirx_aud_clkrate;
u32 fs_audio;
@@ -39,10 +42,21 @@ struct rk628_audioinfo {
bool i2s_enabled_default;
bool i2s_enabled;
int debug;
bool sample_flat;
bool fifo_ints_en;
bool ctsn_ints_en;
bool audio_present;
bool arc_en;
bool underflow;
bool overflow;
bool startthreshold;
int stablelimit;
int stablecount;
struct device *dev;
struct platform_device *pdev;
hdmi_codec_plugged_cb plugged_cb;
rk628_audio_info_cb info_cb;
struct device *codec_dev;
};
struct hdmirx_tmdsclk_cnt {
@@ -296,6 +310,9 @@ static void rk628_hdmirx_audio_fifo_init(struct rk628_audioinfo *aif)
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10001);
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10000);
aif->audio_state.pre_state = aif->audio_state.init_state = INIT_FIFO_STATE*4;
aif->underflow = false;
aif->overflow = false;
aif->startthreshold = false;
}
static void rk628_hdmirx_audio_fifo_initd(struct rk628_audioinfo *aif)
@@ -360,6 +377,25 @@ static void rk628_hdmirx_audio_clk_inc_rate(struct rk628_audioinfo *aif, int dis
aif->audio_state.hdmirx_aud_clkrate = hdmirx_aud_clkrate;
}
static void rk628_hdmirx_audio_clk_ppm_inc(struct rk628_audioinfo *aif, int ppm)
{
int delta, rate, inc;
rate = aif->audio_state.hdmirx_aud_clkrate;
if (ppm < 0) {
ppm = -ppm;
inc = -1;
} else
inc = 1;
delta = div_u64(((uint64_t)rate * ppm + 500000), 1000000);
delta *= inc;
rate += delta;
dev_dbg(aif->dev, "%s: %u to %u(delta:%d)\n",
__func__, aif->audio_state.hdmirx_aud_clkrate, rate, delta);
rk628_clk_set_rate(aif->rk628, CGU_CLK_HDMIRX_AUD, rate);
aif->audio_state.hdmirx_aud_clkrate = rate;
}
static void rk628_hdmirx_audio_set_fs(struct rk628_audioinfo *aif, u32 fs_audio)
{
u32 hdmirx_aud_clkrate_t = fs_audio*128;
@@ -403,6 +439,55 @@ static const char *audio_fifo_err(u32 fifo_status)
return "underflow or overflow";
}
static int rk628_hdmirx_audio_clk_adjust(struct rk628_audioinfo *aif,
int total_offset, int single_offset)
{
int shedule_time = 500;
int ppm = 10;
if (total_offset > 16 && single_offset > 0)
rk628_hdmirx_audio_clk_ppm_inc(aif, ppm);
else if (total_offset < -16 && single_offset < 0)
rk628_hdmirx_audio_clk_ppm_inc(aif, -ppm);
if (total_offset >= 20) {
shedule_time = 200;
} else if (total_offset >= 50) {
shedule_time = 100;
dev_dbg(aif->dev, "%s: decrease shedule time to %d\n", __func__, shedule_time);
} else if (ppm >= 80) {
shedule_time = 50;
dev_dbg(aif->dev, "%s: decrease shedule time to %d\n", __func__, shedule_time);
}
if (!aif->audio_present)
shedule_time = 50;
return shedule_time;
}
static void rk628_hdmirx_audio_state_change(struct rk628_audioinfo *aif, bool on)
{
struct device *dev = aif->rk628->dev;
if (on) {
if (aif->stablecount < aif->stablelimit) {
aif->stablecount++;
dev_info(dev, "wait for audio stable count %d\n", aif->stablecount);
return;
}
if (!aif->audio_present) {
aif->audio_present = true;
dev_info(dev, "audio on\n");
rk628_hdmirx_audio_handle_plugged_change(aif, aif->audio_present);
}
} else {
if (aif->audio_present) {
aif->stablecount = 0;
aif->audio_present = false;
dev_info(dev, "audio off\n");
rk628_hdmirx_audio_handle_plugged_change(aif, aif->audio_present);
}
}
}
static void rk628_csi_delayed_work_audio_v2(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
@@ -412,13 +497,13 @@ static void rk628_csi_delayed_work_audio_v2(struct work_struct *work)
struct rk628 *rk628 = aif->rk628;
u32 fs_audio, sample_flat;
int init_state, pre_state, fifo_status, fifo_ints;
int single_offset, total_offset;
unsigned long delay = 500;
fs_audio = _rk628_hdmirx_audio_fs(aif);
/* read fifo init status */
rk628_i2c_read(rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints);
dev_dbg(rk628->dev, "%s: HDMI_RX_AUD_FIFO_ISTS:%#x\r\n", __func__, fifo_ints);
if (fifo_ints & (AFIF_UNDERFL_ISTS | AFIF_OVERFL_ISTS)) {
dev_warn(rk628->dev, "%s: audio %s %#x, with fs %svalid %d\n",
__func__, audio_fifo_err(fifo_ints), fifo_ints,
@@ -426,7 +511,7 @@ static void rk628_csi_delayed_work_audio_v2(struct work_struct *work)
if (is_validfs(fs_audio))
rk628_hdmirx_audio_set_fs(aif, fs_audio);
rk628_hdmirx_audio_fifo_init(aif);
audio_state->pre_state = 0;
rk628_hdmirx_audio_state_change(aif, 0);
goto exit;
}
@@ -434,9 +519,11 @@ static void rk628_csi_delayed_work_audio_v2(struct work_struct *work)
init_state = audio_state->init_state;
pre_state = audio_state->pre_state;
rk628_i2c_read(rk628, HDMI_RX_AUD_FIFO_FILLSTS1, &fifo_status);
single_offset = fifo_status - pre_state;
total_offset = fifo_status - init_state;
dev_dbg(rk628->dev,
"%s: HDMI_RX_AUD_FIFO_FILLSTS1:%#x, single offset:%d, total offset:%d\n",
__func__, fifo_status, fifo_status - pre_state, fifo_status - init_state);
__func__, fifo_status, single_offset, total_offset);
if (!is_validfs(fs_audio)) {
dev_dbg(rk628->dev, "%s: no supported fs(%u), fifo_status %d\n",
__func__, fs_audio, fifo_status);
@@ -446,33 +533,26 @@ static void rk628_csi_delayed_work_audio_v2(struct work_struct *work)
__func__, audio_state->fs_audio, fs_audio);
rk628_hdmirx_audio_set_fs(aif, fs_audio);
rk628_hdmirx_audio_fifo_init(aif);
audio_state->pre_state = 0;
rk628_hdmirx_audio_state_change(aif, 0);
goto exit;
}
if (fifo_status != 0) {
if (!aif->audio_present) {
dev_info(rk628->dev, "audio on");
aif->audio_present = true;
}
if (fifo_status - init_state > 16 && fifo_status - pre_state > 0)
rk628_hdmirx_audio_clk_inc_rate(aif, 10);
else if (fifo_status - init_state < -16 && fifo_status - pre_state < 0)
rk628_hdmirx_audio_clk_inc_rate(aif, -10);
rk628_hdmirx_audio_state_change(aif, 1);
delay = rk628_hdmirx_audio_clk_adjust(aif, total_offset, single_offset);
} else {
if (aif->audio_present) {
dev_info(rk628->dev, "audio off");
aif->audio_present = false;
}
rk628_hdmirx_audio_state_change(aif, 0);
}
audio_state->pre_state = fifo_status;
rk628_i2c_read(rk628, HDMI_RX_AUD_SPARE, &sample_flat);
sample_flat = sample_flat & AUDS_MAS_SAMPLE_FLAT;
if (!sample_flat)
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_I2S_DATA_OEN_MASK, SW_I2S_DATA_OEN(0));
else
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_I2S_DATA_OEN_MASK, SW_I2S_DATA_OEN(1));
if (aif->i2s_enabled) {
rk628_i2c_read(rk628, HDMI_RX_AUD_SPARE, &sample_flat);
sample_flat = !!(sample_flat & AUDS_MAS_SAMPLE_FLAT);
if (sample_flat != aif->sample_flat) {
dev_info(rk628->dev, "audio sample flat change to %d\n", sample_flat);
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL, I2S_LPCM_BPCUV(0) | I2S_32_16(1) |
(sample_flat ? I2S_DATA_ENABLE_BITS(0xf) : I2S_DATA_ENABLE_BITS(0)));
aif->sample_flat = sample_flat;
}
}
exit:
schedule_delayed_work(&aif->delayed_work_audio, msecs_to_jiffies(delay));
}
@@ -503,10 +583,19 @@ static void rk628_csi_delayed_work_audio(struct work_struct *work)
rk628_i2c_read(aif->rk628, HDMI_RX_AUD_FIFO_FILLSTS1, &cur_state);
dev_dbg(aif->dev, "%s: HDMI_RX_AUD_FIFO_FILLSTS1:%#x, single offset:%d, total offset:%d\n",
__func__, cur_state, cur_state - pre_state, cur_state - init_state);
if (cur_state != 0)
aif->audio_present = true;
else
aif->audio_present = false;
if (cur_state != 0) {
if (!aif->audio_present) {
dev_dbg(aif->dev, "audio on\n");
aif->audio_present = true;
rk628_hdmirx_audio_handle_plugged_change(aif, 1);
}
} else {
if (aif->audio_present) {
dev_dbg(aif->dev, "audio off\n");
aif->audio_present = false;
rk628_hdmirx_audio_handle_plugged_change(aif, 0);
}
}
if ((cur_state - init_state) > 16 && (cur_state - pre_state) > 0)
rk628_hdmirx_audio_clk_inc_rate(aif, 10);
@@ -545,23 +634,110 @@ static void rk628_csi_delayed_work_audio_rate_change(struct work_struct *work)
if (is_validfs(fs_audio))
rk628_hdmirx_audio_set_fs(aif, fs_audio);
rk628_i2c_read(aif->rk628, HDMI_RX_AUD_FIFO_FILLSTS1, &fifo_fillsts);
if (!fifo_fillsts) {
if (!fifo_fillsts)
dev_dbg(aif->dev, "%s underflow after overflow\n", __func__);
rk628_hdmirx_audio_fifo_initd(aif);
} else {
else
dev_dbg(aif->dev, "%s overflow after underflow\n", __func__);
rk628_hdmirx_audio_fifo_initd(aif);
}
rk628_hdmirx_audio_fifo_initd(aif);
aif->audio_present = false;
rk628_hdmirx_audio_handle_plugged_change(aif, 0);
}
mutex_unlock(aif->confctl_mutex);
}
static int rk628_hdmirx_audio_hw_params(struct device *dev, void *data,
struct hdmi_codec_daifmt *daifmt,
struct hdmi_codec_params *params)
{
dev_dbg(dev, "%s\n", __func__);
return 0;
}
static int rk628_hdmirx_audio_startup(struct device *dev, void *data)
{
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)data;
dev_info(dev, "%s: %d\n", __func__, aif->audio_present);
if (aif->audio_present)
return 0;
dev_err(dev, "%s: device is no connected\n", __func__);
return -ENODEV;
}
static void rk628_hdmirx_audio_shutdown(struct device *dev, void *data)
{
dev_dbg(dev, "%s\n", __func__);
}
static int rk628_hdmirx_audio_get_dai_id(struct snd_soc_component *comment,
struct device_node *endpoint)
{
dev_dbg(comment->dev, "%s\n", __func__);
return 0;
}
void rk628_hdmirx_audio_handle_plugged_change(HAUDINFO info, bool plugged)
{
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
if (aif->plugged_cb && aif->codec_dev)
aif->plugged_cb(aif->codec_dev, plugged);
if (aif->info_cb)
aif->info_cb(aif->rk628, plugged);
}
static int rk628_hdmirx_audio_hook_plugged_cb(struct device *dev, void *data,
hdmi_codec_plugged_cb fn,
struct device *codec_dev)
{
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)data;
dev_dbg(dev, "%s\n", __func__);
if (aif->confctl_mutex)
mutex_lock(aif->confctl_mutex);
aif->plugged_cb = fn;
aif->codec_dev = codec_dev;
rk628_hdmirx_audio_handle_plugged_change(aif, aif->audio_present);
if (aif->confctl_mutex)
mutex_unlock(aif->confctl_mutex);
return 0;
}
static const struct hdmi_codec_ops rk628_hdmirx_audio_codec_ops = {
.hw_params = rk628_hdmirx_audio_hw_params,
.audio_startup = rk628_hdmirx_audio_startup,
.audio_shutdown = rk628_hdmirx_audio_shutdown,
.get_dai_id = rk628_hdmirx_audio_get_dai_id,
.hook_plugged_cb = rk628_hdmirx_audio_hook_plugged_cb
};
static int rk628_hdmirx_register_audio_device(struct rk628_audioinfo *aif)
{
struct hdmi_codec_pdata codec_data = {
.ops = &rk628_hdmirx_audio_codec_ops,
.spdif = 1,
.i2s = 1,
.max_i2s_channels = 8,
.data = aif,
};
aif->pdev = platform_device_register_data(aif->dev,
HDMI_CODEC_DRV_NAME,
PLATFORM_DEVID_AUTO,
&codec_data,
sizeof(codec_data));
return PTR_ERR_OR_ZERO(aif->pdev);
}
HAUDINFO rk628_hdmirx_audioinfo_alloc(struct device *dev,
struct mutex *confctl_mutex,
struct rk628 *rk628,
bool en)
bool en,
rk628_audio_info_cb info_cb)
{
struct rk628_audioinfo *aif;
int ret;
aif = devm_kzalloc(dev, sizeof(*aif), GFP_KERNEL);
if (!aif)
@@ -577,6 +753,13 @@ HAUDINFO rk628_hdmirx_audioinfo_alloc(struct device *dev,
aif->rk628 = rk628;
aif->i2s_enabled_default = en;
aif->dev = dev;
aif->audio_present = false;
aif->info_cb = info_cb;
ret = rk628_hdmirx_register_audio_device(aif);
if (ret) {
dev_err(dev, "register audio_driver failed!\n");
return NULL;
}
return aif;
}
EXPORT_SYMBOL(rk628_hdmirx_audioinfo_alloc);
@@ -614,6 +797,8 @@ void rk628_hdmirx_audio_destroy(HAUDINFO info)
rk628_hdmirx_audio_cancel_work_audio(aif, true);
if (rk628->version < RK628F_VERSION)
rk628_hdmirx_audio_cancel_work_rate_change(aif, true);
if (aif->pdev)
platform_device_unregister(aif->pdev);
aif->confctl_mutex = NULL;
aif->rk628 = NULL;
}
@@ -639,21 +824,42 @@ int rk628_hdmirx_audio_fs(HAUDINFO info)
}
EXPORT_SYMBOL(rk628_hdmirx_audio_fs);
bool rk628_hdmirx_get_arc_enable(HAUDINFO info)
{
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
if (!aif)
return false;
return aif->arc_en;
}
EXPORT_SYMBOL(rk628_hdmirx_get_arc_enable);
int rk628_hdmirx_set_arc_enable(HAUDINFO info, bool enabled)
{
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
if (!aif)
return false;
return aif->arc_en = enabled;
}
EXPORT_SYMBOL(rk628_hdmirx_set_arc_enable);
void rk628_hdmirx_audio_i2s_ctrl(HAUDINFO info, bool enable)
{
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
if (enable == aif->i2s_enabled)
if (enable == aif->i2s_enabled || aif->i2s_enabled_default)
return;
if (enable) {
if (enable && !aif->sample_flat) {
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL,
I2S_LPCM_BPCUV(0) |
I2S_32_16(1));
I2S_LPCM_BPCUV(0) | I2S_32_16(1) |
I2S_DATA_ENABLE_BITS(0));
} else {
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL,
I2S_LPCM_BPCUV(0) |
I2S_32_16(1) |
I2S_ENABLE_BITS(0x3f));
I2S_LPCM_BPCUV(0) | I2S_32_16(1) |
I2S_DATA_ENABLE_BITS(0xf));
}
aif->i2s_enabled = enable;
}
@@ -674,14 +880,19 @@ void rk628_hdmirx_audio_setup(HAUDINFO info)
aif->audio_state.init_state = INIT_FIFO_STATE*4;
aif->audio_state.fifo_int = false;
aif->audio_state.audio_enable = false;
aif->sample_flat = false;
aif->fifo_ints_en = false;
aif->ctsn_ints_en = false;
aif->i2s_enabled = false;
aif->underflow = false;
aif->overflow = false;
aif->startthreshold = false;
aif->stablelimit = 0;
if (rk628->version >= RK628F_VERSION)
rk628_i2c_write(rk628, CRU_MODE_CON00, HIWORD_UPDATE(1, 4, 4));
rk628_hdmirx_audio_clk_set_rate(aif, 5644800);
rk628_hdmirx_audio_clk_set_rate(aif, DEFAULT_AUDIO_CLK);
/* manual aud CTS */
rk628_i2c_write(aif->rk628, HDMI_RX_AUDPLL_GEN_CTS, audio_pll_cts);
/* manual aud N */
@@ -697,8 +908,8 @@ void rk628_hdmirx_audio_setup(HAUDINFO info)
AFIF_TH_START_MASK |
AFIF_TH_MAX_MASK |
AFIF_TH_MIN_MASK,
AFIF_TH_START(64) |
AFIF_TH_MAX(8) |
AFIF_TH_START(INIT_FIFO_STATE) |
AFIF_TH_MAX(INIT_FIFO_STATE*2) |
AFIF_TH_MIN(8));
/* AUTO_VMUTE */
@@ -709,8 +920,8 @@ void rk628_hdmirx_audio_setup(HAUDINFO info)
AFIF_SUBPACKETS(1));
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL,
I2S_LPCM_BPCUV(0) |
I2S_32_16(1)|
(aif->i2s_enabled_default ? 0 : I2S_ENABLE_BITS(0x3f)));
I2S_32_16(1) |
(aif->i2s_enabled_default ? 0 : I2S_DATA_ENABLE_BITS(0xf)));
aif->i2s_enabled = aif->i2s_enabled_default;
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_MUTE_CTRL,
APPLY_INT_MUTE(0) |
@@ -726,8 +937,6 @@ void rk628_hdmirx_audio_setup(HAUDINFO info)
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_CHEXTR_CTRL,
AUD_LAYOUT_CTRL(1));
if (rk628->version >= RK628F_VERSION) {
rk628_i2c_update_bits(aif->rk628, HDMI_RX_DMI_DISABLE_IF,
AUD_ENABLE_MASK, AUD_ENABLE(1));
schedule_delayed_work(&aif->delayed_work_audio, msecs_to_jiffies(1000));
} else {
aif->ctsn_ints_en = true;
@@ -1027,6 +1236,17 @@ void rk628_hdmirx_cec_irq(struct rk628 *rk628, struct rk628_hdmirx_cec *cec)
}
EXPORT_SYMBOL(rk628_hdmirx_cec_irq);
static void rk628_delayed_work_cec(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct rk628_hdmirx_cec *cec = container_of(dwork, struct rk628_hdmirx_cec,
delayed_work_cec);
bool en = rk628_hdmirx_tx_5v_power_detect(cec->rk628->hdmirx_det_gpio);
cec->cec_hpd = en;
cec_queue_pin_hpd_event(cec->adap, en, ktime_get());
}
struct rk628_hdmirx_cec *rk628_hdmirx_cec_register(struct rk628 *rk628)
{
struct rk628_hdmirx_cec *cec;
@@ -1068,6 +1288,8 @@ struct rk628_hdmirx_cec *rk628_hdmirx_cec_register(struct rk628 *rk628)
/* override the module pointer */
cec->adap->owner = THIS_MODULE;
INIT_DELAYED_WORK(&cec->delayed_work_cec, rk628_delayed_work_cec);
ret = devm_add_action(cec->dev, rk628_hdmirx_cec_del, cec);
if (ret) {
cec_delete_adapter(cec->adap);
@@ -1102,6 +1324,8 @@ struct rk628_hdmirx_cec *rk628_hdmirx_cec_register(struct rk628 *rk628)
*/
devm_remove_action(cec->dev, rk628_hdmirx_cec_del, cec);
schedule_delayed_work(&cec->delayed_work_cec, msecs_to_jiffies(10000));
return cec;
}
EXPORT_SYMBOL(rk628_hdmirx_cec_register);
@@ -1121,7 +1345,11 @@ void rk628_hdmirx_cec_hpd(struct rk628_hdmirx_cec *cec, bool en)
if (!cec || !cec->adap)
return;
cec_queue_pin_hpd_event(cec->adap, en, ktime_get());
rk628_dbg(cec->rk628, "%s: cec_hpd:%d, en:%d\n", __func__, cec->cec_hpd, en);
if (cec->cec_hpd != en) {
cec->cec_hpd = en;
cec_queue_pin_hpd_event(cec->adap, en, ktime_get());
}
}
EXPORT_SYMBOL(rk628_hdmirx_cec_hpd);
@@ -1131,6 +1359,9 @@ void rk628_hdmirx_cec_state_reconfiguration(struct rk628 *rk628,
unsigned int irqs;
u32 val;
/* clk_hdmirx_cec = 32.768k */
rk628_clk_set_rate(rk628, CGU_CLK_HDMIRX_CEC, 32768);
rk628_i2c_write(rk628, HDMI_RX_CEC_ADDR_L, cec->addresses & 0xff);
rk628_i2c_write(rk628, HDMI_RX_CEC_ADDR_H, (cec->addresses >> 8) & 0xff);

View File

@@ -188,6 +188,8 @@
#define HDMI_RX_AUD_SAO_CTRL (HDMI_RX_BASE + 0x0260)
#define I2S_ENABLE_BITS_MASK GENMASK(10, 5)
#define I2S_ENABLE_BITS(x) UPDATE(x, 10, 5)
#define I2S_CLK_ENABLE_BITS(x) UPDATE(x, 10, 9)
#define I2S_DATA_ENABLE_BITS(x) UPDATE(x, 8, 5)
#define I2S_LPCM_BPCUV_MASK BIT(11)
#define I2S_LPCM_BPCUV(x) UPDATE(x, 11, 11)
#define I2S_32_16_MASK BIT(0)
@@ -486,17 +488,21 @@ struct rk628_hdmirx_cec {
unsigned int tx_status;
bool tx_done;
bool rx_done;
bool cec_hpd;
struct cec_notifier *notify;
struct delayed_work delayed_work_cec;
};
void rk628_hdmirx_set_hdcp(struct rk628 *rk628, struct rk628_hdcp *hdcp, bool en);
void rk628_hdmirx_controller_setup(struct rk628 *rk628);
typedef void *HAUDINFO;
typedef void (*rk628_audio_info_cb)(struct rk628 *rk628, bool on);
HAUDINFO rk628_hdmirx_audioinfo_alloc(struct device *dev,
struct mutex *confctl_mutex,
struct rk628 *rk628,
bool en);
bool en,
rk628_audio_info_cb info_cb);
void rk628_hdmirx_audio_destroy(HAUDINFO info);
void rk628_hdmirx_audio_setup(HAUDINFO info);
void rk628_hdmirx_audio_cancel_work_audio(HAUDINFO info, bool sync);
@@ -504,6 +510,9 @@ void rk628_hdmirx_audio_cancel_work_rate_change(HAUDINFO info, bool sync);
bool rk628_hdmirx_audio_present(HAUDINFO info);
int rk628_hdmirx_audio_fs(HAUDINFO info);
void rk628_hdmirx_audio_i2s_ctrl(HAUDINFO info, bool enable);
bool rk628_hdmirx_get_arc_enable(HAUDINFO info);
int rk628_hdmirx_set_arc_enable(HAUDINFO info, bool enabled);
void rk628_hdmirx_audio_handle_plugged_change(HAUDINFO info, bool plugged);
/* for audio isr process */
bool rk628_audio_fifoints_enabled(HAUDINFO info);

View File

@@ -36,6 +36,21 @@ struct rockchip_csu {
static struct rockchip_csu *rk_csu;
static DEFINE_MUTEX(csu_lock);
static struct csu_bus *rockchip_csu_get_bus(unsigned int bus_id)
{
int i;
if (!rk_csu || !rk_csu->bus)
return NULL;
for (i = 0; i < rk_csu->bus_cnt; i++) {
if (bus_id == rk_csu->bus[i].id)
return &rk_csu->bus[i];
}
return NULL;
}
static int rockchip_csu_sip_config(struct device *dev, u32 bus_id, u32 cfg,
u32 enable_msk)
{
@@ -91,7 +106,7 @@ static int csu_disable(struct csu_clk *clk, bool disable)
return 0;
if (clk->bus_id >= rk_csu->bus_cnt)
return 0;
bus = &rk_csu->bus[clk->bus_id];
bus = rockchip_csu_get_bus(clk->bus_id);
if (!bus)
return 0;
@@ -138,7 +153,7 @@ int rockchip_csu_set_div(struct csu_clk *clk, unsigned int div)
return 0;
if (clk->bus_id >= rk_csu->bus_cnt)
return 0;
bus = &rk_csu->bus[clk->bus_id];
bus = rockchip_csu_get_bus(clk->bus_id);
if (!bus)
return 0;

View File

@@ -588,6 +588,7 @@ static int rkvdec2_isr(struct mpp_dev *mpp)
struct rkvdec2_task *task = NULL;
struct mpp_task *mpp_task = mpp->cur_task;
struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp);
struct rkvdec_link_info *link_info = mpp->var->hw_info->link_info;
/* FIXME use a spin lock here */
if (!mpp_task) {
@@ -601,8 +602,7 @@ static int rkvdec2_isr(struct mpp_dev *mpp)
task->irq_status = mpp->irq_status;
mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n", task->irq_status);
err_mask = RKVDEC_COLMV_REF_ERR_STA | RKVDEC_BUF_EMPTY_STA |
RKVDEC_TIMEOUT_STA | RKVDEC_ERROR_STA;
err_mask = link_info->err_mask;
if (err_mask & task->irq_status) {
atomic_inc(&mpp->reset_request);
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) {

View File

@@ -67,10 +67,6 @@
#define RKVDEC_READY_STA BIT(2)
#define RKVDEC_IRQ_RAW BIT(1)
#define RKVDEC_IRQ BIT(0)
#define RKVDEC_INT_ERROR_MASK (RKVDEC_COLMV_REF_ERR_STA |\
RKVDEC_BUF_EMPTY_STA |\
RKVDEC_TIMEOUT_STA |\
RKVDEC_ERROR_STA)
#define RKVDEC_PERF_WORKING_CNT 0x41c
/* perf sel reference register */

View File

@@ -79,6 +79,7 @@ struct rkvdec_link_info rkvdec_link_v2_hw_info = {
},
.irq_base = 0x00,
.next_addr_base = 0x1c,
.err_mask = 0xf0,
};
/* vdpu34x link hw info for rk356x */
@@ -140,6 +141,7 @@ struct rkvdec_link_info rkvdec_link_rk356x_hw_info = {
},
.irq_base = 0x00,
.next_addr_base = 0x1c,
.err_mask = 0xf0,
};
/* vdpu382 link hw info */
@@ -201,6 +203,7 @@ struct rkvdec_link_info rkvdec_link_vdpu382_hw_info = {
},
.irq_base = 0x00,
.next_addr_base = 0x1c,
.err_mask = 0xf0,
};
/* vdpu383 link hw info */
@@ -1102,7 +1105,7 @@ static void rkvdec2_link_try_dequeue(struct mpp_dev *mpp)
mpp_task->session->index, mpp_task->task_index,
irq_status, timeout_flag, abort_flag);
if (irq_status & RKVDEC_INT_ERROR_MASK) {
if (irq_status & info->err_mask) {
dev_err(mpp->dev,
"session %d task %d irq_status %#08x timeout %u abort %u\n",
mpp_task->session->index, mpp_task->task_index,
@@ -1851,10 +1854,11 @@ irqreturn_t rkvdec2_soft_ccu_irq(int irq, void *param)
{
struct mpp_dev *mpp = param;
u32 irq_status = mpp_read_relaxed(mpp, RKVDEC_REG_INT_EN);
struct rkvdec_link_info *link_info = mpp->var->hw_info->link_info;
if (irq_status & RKVDEC_IRQ_RAW) {
mpp_debug(DEBUG_IRQ_STATUS, "irq_status=%08x\n", irq_status);
if (irq_status & RKVDEC_INT_ERROR_MASK) {
if (irq_status & link_info->err_mask) {
atomic_inc(&mpp->reset_request);
atomic_inc(&mpp->queue->reset_request);
}
@@ -2214,7 +2218,7 @@ static int rkvdec2_hard_ccu_dequeue(struct mpp_taskqueue *queue,
mpp_debug(DEBUG_IRQ_CHECK,
"session %d task %d w:h[%d %d] err %d irq_status %#x timeout=%u abort=%u iova %08x next %08x ccu[%d %d]\n",
mpp_task->session->index, mpp_task->task_index, task->width,
task->height, !!(irq_status & RKVDEC_INT_ERROR_MASK), irq_status,
task->height, !!(irq_status & hw->err_mask), irq_status,
timeout_flag, abort_flag, (u32)task->table->iova,
((u32 *)task->table->vaddr)[hw->tb_reg_next],
ccu_decoded_num, ccu_total_dec_num);
@@ -2251,7 +2255,7 @@ static int rkvdec2_hard_ccu_dequeue(struct mpp_taskqueue *queue,
list_del_init(&mpp_task->queue_link);
/* Wake up the GET thread */
wake_up(&mpp_task->wait);
if ((irq_status & RKVDEC_INT_ERROR_MASK) || timeout_flag) {
if ((irq_status & hw->err_mask) || timeout_flag) {
pr_err("session %d task %d irq_status %#x timeout=%u abort=%u\n",
mpp_task->session->index, mpp_task->task_index,
irq_status, timeout_flag, abort_flag);