media: i2c: adv748x: Handle TX[A|B] power management
As the driver is now allowed to probe with a single output endpoint, power management routines shall now take into account the case a CSI-2 TX is not enabled. Unify the adv748x_tx_power() routine to handle transparently TXA and TXB, and enable the CSI-2 outputs conditionally. Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
eccf442ce1
commit
6bc3ea7a61
|
@ -282,7 +282,7 @@ static int adv748x_afe_s_stream(struct v4l2_subdev *sd, int enable)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
ret = adv748x_txb_power(state, enable);
|
||||
ret = adv748x_tx_power(&state->txb, enable);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
|
|
|
@ -288,11 +288,16 @@ static const struct adv748x_reg_value adv748x_power_down_txb_1lane[] = {
|
|||
{ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
|
||||
};
|
||||
|
||||
int adv748x_txa_power(struct adv748x_state *state, bool on)
|
||||
int adv748x_tx_power(struct adv748x_csi2 *tx, bool on)
|
||||
{
|
||||
struct adv748x_state *state = tx->state;
|
||||
const struct adv748x_reg_value *reglist;
|
||||
int val;
|
||||
|
||||
val = txa_read(state, ADV748X_CSI_FS_AS_LS);
|
||||
if (!is_tx_enabled(tx))
|
||||
return 0;
|
||||
|
||||
val = tx_read(tx, ADV748X_CSI_FS_AS_LS);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
|
@ -305,31 +310,13 @@ int adv748x_txa_power(struct adv748x_state *state, bool on)
|
|||
"Enabling with unknown bit set");
|
||||
|
||||
if (on)
|
||||
return adv748x_write_regs(state, adv748x_power_up_txa_4lane);
|
||||
reglist = is_txa(tx) ? adv748x_power_up_txa_4lane :
|
||||
adv748x_power_up_txb_1lane;
|
||||
else
|
||||
reglist = is_txa(tx) ? adv748x_power_down_txa_4lane :
|
||||
adv748x_power_down_txb_1lane;
|
||||
|
||||
return adv748x_write_regs(state, adv748x_power_down_txa_4lane);
|
||||
}
|
||||
|
||||
int adv748x_txb_power(struct adv748x_state *state, bool on)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = txb_read(state, ADV748X_CSI_FS_AS_LS);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
/*
|
||||
* This test against BIT(6) is not documented by the datasheet, but was
|
||||
* specified in the downstream driver.
|
||||
* Track with a WARN_ONCE to determine if it is ever set by HW.
|
||||
*/
|
||||
WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN),
|
||||
"Enabling with unknown bit set");
|
||||
|
||||
if (on)
|
||||
return adv748x_write_regs(state, adv748x_power_up_txb_1lane);
|
||||
|
||||
return adv748x_write_regs(state, adv748x_power_down_txb_1lane);
|
||||
return adv748x_write_regs(state, reglist);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
@ -478,6 +465,7 @@ static const struct adv748x_reg_value adv748x_init_txb_1lane[] = {
|
|||
static int adv748x_reset(struct adv748x_state *state)
|
||||
{
|
||||
int ret;
|
||||
u8 regval = ADV748X_IO_10_PIX_OUT_EN;
|
||||
|
||||
ret = adv748x_write_regs(state, adv748x_sw_reset);
|
||||
if (ret < 0)
|
||||
|
@ -492,22 +480,24 @@ static int adv748x_reset(struct adv748x_state *state)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
adv748x_txa_power(state, 0);
|
||||
adv748x_tx_power(&state->txa, 0);
|
||||
|
||||
/* Init and power down TXB */
|
||||
ret = adv748x_write_regs(state, adv748x_init_txb_1lane);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
adv748x_txb_power(state, 0);
|
||||
adv748x_tx_power(&state->txb, 0);
|
||||
|
||||
/* Disable chip powerdown & Enable HDMI Rx block */
|
||||
io_write(state, ADV748X_IO_PD, ADV748X_IO_PD_RX_EN);
|
||||
|
||||
/* Enable 4-lane CSI Tx & Pixel Port */
|
||||
io_write(state, ADV748X_IO_10, ADV748X_IO_10_CSI4_EN |
|
||||
ADV748X_IO_10_CSI1_EN |
|
||||
ADV748X_IO_10_PIX_OUT_EN);
|
||||
/* Conditionally enable TXa and TXb. */
|
||||
if (is_tx_enabled(&state->txa))
|
||||
regval |= ADV748X_IO_10_CSI4_EN;
|
||||
if (is_tx_enabled(&state->txb))
|
||||
regval |= ADV748X_IO_10_CSI1_EN;
|
||||
io_write(state, ADV748X_IO_10, regval);
|
||||
|
||||
/* Use vid_std and v_freq as freerun resolution for CP */
|
||||
cp_clrset(state, ADV748X_CP_CLMP_POS, ADV748X_CP_CLMP_POS_DIS_AUTO,
|
||||
|
|
|
@ -14,11 +14,6 @@
|
|||
|
||||
#include "adv748x.h"
|
||||
|
||||
static bool is_txa(struct adv748x_csi2 *tx)
|
||||
{
|
||||
return tx == &tx->state->txa;
|
||||
}
|
||||
|
||||
static int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx,
|
||||
unsigned int vc)
|
||||
{
|
||||
|
|
|
@ -358,7 +358,7 @@ static int adv748x_hdmi_s_stream(struct v4l2_subdev *sd, int enable)
|
|||
|
||||
mutex_lock(&state->mutex);
|
||||
|
||||
ret = adv748x_txa_power(state, enable);
|
||||
ret = adv748x_tx_power(&state->txa, enable);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ struct adv748x_csi2 {
|
|||
#define notifier_to_csi2(n) container_of(n, struct adv748x_csi2, notifier)
|
||||
#define adv748x_sd_to_csi2(sd) container_of(sd, struct adv748x_csi2, sd)
|
||||
#define is_tx_enabled(_tx) ((_tx)->state->endpoints[(_tx)->port] != NULL)
|
||||
#define is_txa(_tx) ((_tx) == &(_tx)->state->txa)
|
||||
|
||||
enum adv748x_hdmi_pads {
|
||||
ADV748X_HDMI_SINK,
|
||||
|
@ -374,9 +375,6 @@ int adv748x_write_block(struct adv748x_state *state, int client_page,
|
|||
#define cp_write(s, r, v) adv748x_write(s, ADV748X_PAGE_CP, r, v)
|
||||
#define cp_clrset(s, r, m, v) cp_write(s, r, (cp_read(s, r) & ~m) | v)
|
||||
|
||||
#define txa_read(s, r) adv748x_read(s, ADV748X_PAGE_TXA, r)
|
||||
#define txb_read(s, r) adv748x_read(s, ADV748X_PAGE_TXB, r)
|
||||
|
||||
#define tx_read(t, r) adv748x_read(t->state, t->page, r)
|
||||
#define tx_write(t, r, v) adv748x_write(t->state, t->page, r, v)
|
||||
|
||||
|
@ -396,8 +394,7 @@ void adv748x_subdev_init(struct v4l2_subdev *sd, struct adv748x_state *state,
|
|||
int adv748x_register_subdevs(struct adv748x_state *state,
|
||||
struct v4l2_device *v4l2_dev);
|
||||
|
||||
int adv748x_txa_power(struct adv748x_state *state, bool on);
|
||||
int adv748x_txb_power(struct adv748x_state *state, bool on);
|
||||
int adv748x_tx_power(struct adv748x_csi2 *tx, bool on);
|
||||
|
||||
int adv748x_afe_init(struct adv748x_afe *afe);
|
||||
void adv748x_afe_cleanup(struct adv748x_afe *afe);
|
||||
|
|
Loading…
Reference in New Issue