mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-28 12:25:31 +00:00
[media] adv7604: Support hot-plug detect control through a GPIO
Add support for optional GPIO-controlled HPD pins in addition to the ADV7604-specific hotplug notifier. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
parent
c72a53ce05
commit
e9d50e9e70
@ -28,6 +28,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -135,6 +136,8 @@ struct adv7604_state {
|
||||
const struct adv7604_chip_info *info;
|
||||
struct adv7604_platform_data pdata;
|
||||
|
||||
struct gpio_desc *hpd_gpio[4];
|
||||
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pads[ADV7604_PAD_MAX];
|
||||
unsigned int source_pad;
|
||||
@ -598,6 +601,20 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void adv7604_set_hpd(struct adv7604_state *state, unsigned int hpd)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < state->info->num_dv_ports; ++i) {
|
||||
if (IS_ERR(state->hpd_gpio[i]))
|
||||
continue;
|
||||
|
||||
gpiod_set_value_cansleep(state->hpd_gpio[i], hpd & BIT(i));
|
||||
}
|
||||
|
||||
v4l2_subdev_notify(&state->sd, ADV7604_HOTPLUG, &hpd);
|
||||
}
|
||||
|
||||
static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
@ -607,7 +624,7 @@ static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
|
||||
|
||||
v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
|
||||
|
||||
v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
|
||||
adv7604_set_hpd(state, state->edid.present);
|
||||
}
|
||||
|
||||
static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
|
||||
@ -2047,7 +2064,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
|
||||
struct adv7604_state *state = to_state(sd);
|
||||
const struct adv7604_chip_info *info = state->info;
|
||||
int spa_loc;
|
||||
int tmp = 0;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
@ -2058,7 +2074,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
|
||||
if (edid->blocks == 0) {
|
||||
/* Disable hotplug and I2C access to EDID RAM from DDC port */
|
||||
state->edid.present &= ~(1 << edid->pad);
|
||||
v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
|
||||
adv7604_set_hpd(state, state->edid.present);
|
||||
rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
|
||||
|
||||
/* Fall back to a 16:9 aspect ratio */
|
||||
@ -2082,7 +2098,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
|
||||
|
||||
/* Disable hotplug and I2C access to EDID RAM from DDC port */
|
||||
cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
|
||||
v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
|
||||
adv7604_set_hpd(state, 0);
|
||||
rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
|
||||
|
||||
spa_loc = get_edid_spa_location(edid->edid);
|
||||
@ -2678,6 +2694,19 @@ static int adv7604_probe(struct i2c_client *client,
|
||||
return -ENODEV;
|
||||
}
|
||||
state->pdata = *pdata;
|
||||
|
||||
/* Request GPIOs. */
|
||||
for (i = 0; i < state->info->num_dv_ports; ++i) {
|
||||
state->hpd_gpio[i] =
|
||||
devm_gpiod_get_index(&client->dev, "hpd", i);
|
||||
if (IS_ERR(state->hpd_gpio[i]))
|
||||
continue;
|
||||
|
||||
gpiod_set_value_cansleep(state->hpd_gpio[i], 0);
|
||||
|
||||
v4l_info(client, "Handling HPD %u GPIO\n", i);
|
||||
}
|
||||
|
||||
state->timings = cea640x480;
|
||||
state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user