Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 105 additions & 75 deletions drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,88 +887,111 @@ static const struct drm_edid *adv7511_bridge_edid_read(struct drm_bridge *bridge
return adv7511_edid_read(adv, connector);
}

static int adv7511_bridge_hdmi_clear_infoframe(struct drm_bridge *bridge,
enum hdmi_infoframe_type type)
static int adv7511_bridge_hdmi_clear_audio_infoframe(struct drm_bridge *bridge)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

switch (type) {
case HDMI_INFOFRAME_TYPE_AUDIO:
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
break;
case HDMI_INFOFRAME_TYPE_AVI:
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
break;
case HDMI_INFOFRAME_TYPE_SPD:
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPD);
break;
case HDMI_INFOFRAME_TYPE_VENDOR:
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);
break;
default:
drm_dbg_driver(adv7511->bridge.dev, "Unsupported HDMI InfoFrame %x\n", type);
break;
}
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);

return 0;
}

static int adv7511_bridge_hdmi_write_infoframe(struct drm_bridge *bridge,
enum hdmi_infoframe_type type,
const u8 *buffer, size_t len)
static int adv7511_bridge_hdmi_clear_avi_infoframe(struct drm_bridge *bridge)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

switch (type) {
case HDMI_INFOFRAME_TYPE_AUDIO:
/* send current Audio infoframe values while updating */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(5), BIT(5));

/* The Audio infoframe id is not configurable */
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME_VERSION,
buffer + 1, len - 1);

/* use Audio infoframe updated info */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(5), 0);

adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
break;
case HDMI_INFOFRAME_TYPE_AVI:
/* send current AVI infoframe values while updating */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(6), BIT(6));

/* The AVI infoframe id is not configurable */
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
buffer + 1, len - 1);

regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME_LENGTH, 0x2);
regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(1), 0x1);

/* use AVI infoframe updated info */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(6), 0);

adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
break;
case HDMI_INFOFRAME_TYPE_SPD:
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPD);
regmap_bulk_write(adv7511->regmap_packet, ADV7511_PACKET_SPD(0),
buffer, len);
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_SPD);
break;
case HDMI_INFOFRAME_TYPE_VENDOR:
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);
regmap_bulk_write(adv7511->regmap_packet, ADV7511_PACKET_SPARE1(0),
buffer, len);
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);
break;
default:
drm_dbg_driver(adv7511->bridge.dev, "Unsupported HDMI InfoFrame %x\n", type);
break;
}
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);

return 0;
}

static int adv7511_bridge_hdmi_clear_spd_infoframe(struct drm_bridge *bridge)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPD);

return 0;
}

static int adv7511_bridge_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);

return 0;
}

static int adv7511_bridge_hdmi_write_audio_infoframe(struct drm_bridge *bridge,
const u8 *buffer, size_t len)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

/* send current Audio infoframe values while updating */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(5), BIT(5));

/* The Audio infoframe id is not configurable */
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME_VERSION,
buffer + 1, len - 1);

/* use Audio infoframe updated info */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(5), 0);

adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);

return 0;
}

static int adv7511_bridge_hdmi_write_avi_infoframe(struct drm_bridge *bridge,
const u8 *buffer, size_t len)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

/* send current AVI infoframe values while updating */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(6), BIT(6));

/* The AVI infoframe id is not configurable */
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
buffer + 1, len - 1);

regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME_LENGTH, 0x2);
regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(1), 0x1);

/* use AVI infoframe updated info */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(6), 0);

adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);

return 0;
}

static int adv7511_bridge_hdmi_write_spd_infoframe(struct drm_bridge *bridge,
const u8 *buffer, size_t len)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPD);
regmap_bulk_write(adv7511->regmap_packet, ADV7511_PACKET_SPD(0),
buffer, len);
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_SPD);

return 0;
}

static int adv7511_bridge_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge,
const u8 *buffer, size_t len)
{
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);

adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);
regmap_bulk_write(adv7511->regmap_packet, ADV7511_PACKET_SPARE1(0),
buffer, len);
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);

return 0;
}
Expand All @@ -986,8 +1009,14 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,

.hdmi_tmds_char_rate_valid = adv7511_bridge_hdmi_tmds_char_rate_valid,
.hdmi_clear_infoframe = adv7511_bridge_hdmi_clear_infoframe,
.hdmi_write_infoframe = adv7511_bridge_hdmi_write_infoframe,
.hdmi_clear_audio_infoframe = adv7511_bridge_hdmi_clear_audio_infoframe,
.hdmi_write_audio_infoframe = adv7511_bridge_hdmi_write_audio_infoframe,
.hdmi_clear_avi_infoframe = adv7511_bridge_hdmi_clear_avi_infoframe,
.hdmi_write_avi_infoframe = adv7511_bridge_hdmi_write_avi_infoframe,
.hdmi_clear_spd_infoframe = adv7511_bridge_hdmi_clear_spd_infoframe,
.hdmi_write_spd_infoframe = adv7511_bridge_hdmi_write_spd_infoframe,
.hdmi_clear_hdmi_infoframe = adv7511_bridge_hdmi_clear_hdmi_infoframe,
.hdmi_write_hdmi_infoframe = adv7511_bridge_hdmi_write_hdmi_infoframe,

.hdmi_audio_startup = adv7511_hdmi_audio_startup,
.hdmi_audio_prepare = adv7511_hdmi_audio_prepare,
Expand Down Expand Up @@ -1322,7 +1351,8 @@ static int adv7511_probe(struct i2c_client *i2c)

adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_EDID |
DRM_BRIDGE_OP_HDMI;
DRM_BRIDGE_OP_HDMI |
DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME;
if (adv7511->i2c_main->irq)
adv7511->bridge.ops |= DRM_BRIDGE_OP_HPD;

Expand Down
95 changes: 49 additions & 46 deletions drivers/gpu/drm/bridge/ite-it6263.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,61 +759,62 @@ it6263_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
return MODE_OK;
}

static int it6263_hdmi_clear_infoframe(struct drm_bridge *bridge,
enum hdmi_infoframe_type type)
static int it6263_hdmi_clear_avi_infoframe(struct drm_bridge *bridge)
{
struct it6263 *it = bridge_to_it6263(bridge);

switch (type) {
case HDMI_INFOFRAME_TYPE_AVI:
regmap_write(it->hdmi_regmap, HDMI_REG_AVI_INFOFRM_CTRL, 0);
break;
case HDMI_INFOFRAME_TYPE_VENDOR:
regmap_write(it->hdmi_regmap, HDMI_REG_PKT_NULL_CTRL, 0);
break;
default:
dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
}
regmap_write(it->hdmi_regmap, HDMI_REG_AVI_INFOFRM_CTRL, 0);

return 0;
}

static int it6263_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge)
{
struct it6263 *it = bridge_to_it6263(bridge);

regmap_write(it->hdmi_regmap, HDMI_REG_PKT_NULL_CTRL, 0);

return 0;
}

static int it6263_hdmi_write_infoframe(struct drm_bridge *bridge,
enum hdmi_infoframe_type type,
const u8 *buffer, size_t len)
static int it6263_hdmi_write_avi_infoframe(struct drm_bridge *bridge,
const u8 *buffer, size_t len)
{
struct it6263 *it = bridge_to_it6263(bridge);
struct regmap *regmap = it->hdmi_regmap;

switch (type) {
case HDMI_INFOFRAME_TYPE_AVI:
/* write the first AVI infoframe data byte chunk(DB1-DB5) */
regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
HDMI_AVI_DB_CHUNK1_SIZE);

/* write the second AVI infoframe data byte chunk(DB6-DB13) */
regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
&buffer[HDMI_INFOFRAME_HEADER_SIZE +
HDMI_AVI_DB_CHUNK1_SIZE],
HDMI_AVI_DB_CHUNK2_SIZE);

/* write checksum */
regmap_write(regmap, HDMI_REG_AVI_CSUM, buffer[3]);

regmap_write(regmap, HDMI_REG_AVI_INFOFRM_CTRL,
ENABLE_PKT | REPEAT_PKT);
break;
case HDMI_INFOFRAME_TYPE_VENDOR:
/* write header and payload */
regmap_bulk_write(regmap, HDMI_REG_PKT_HB(0), buffer, len);

regmap_write(regmap, HDMI_REG_PKT_NULL_CTRL,
ENABLE_PKT | REPEAT_PKT);
break;
default:
dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
}
/* write the first AVI infoframe data byte chunk(DB1-DB5) */
regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
HDMI_AVI_DB_CHUNK1_SIZE);

/* write the second AVI infoframe data byte chunk(DB6-DB13) */
regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
&buffer[HDMI_INFOFRAME_HEADER_SIZE +
HDMI_AVI_DB_CHUNK1_SIZE],
HDMI_AVI_DB_CHUNK2_SIZE);

/* write checksum */
regmap_write(regmap, HDMI_REG_AVI_CSUM, buffer[3]);

regmap_write(regmap, HDMI_REG_AVI_INFOFRM_CTRL,
ENABLE_PKT | REPEAT_PKT);

return 0;
}

static int it6263_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge,
const u8 *buffer, size_t len)
{
struct it6263 *it = bridge_to_it6263(bridge);
struct regmap *regmap = it->hdmi_regmap;

/* write header and payload */
regmap_bulk_write(regmap, HDMI_REG_PKT_HB(0), buffer, len);

regmap_write(regmap, HDMI_REG_PKT_NULL_CTRL,
ENABLE_PKT | REPEAT_PKT);


return 0;
}
Expand All @@ -830,8 +831,10 @@ static const struct drm_bridge_funcs it6263_bridge_funcs = {
.edid_read = it6263_bridge_edid_read,
.atomic_get_input_bus_fmts = it6263_bridge_atomic_get_input_bus_fmts,
.hdmi_tmds_char_rate_valid = it6263_hdmi_tmds_char_rate_valid,
.hdmi_clear_infoframe = it6263_hdmi_clear_infoframe,
.hdmi_write_infoframe = it6263_hdmi_write_infoframe,
.hdmi_clear_avi_infoframe = it6263_hdmi_clear_avi_infoframe,
.hdmi_write_avi_infoframe = it6263_hdmi_write_avi_infoframe,
.hdmi_clear_hdmi_infoframe = it6263_hdmi_clear_hdmi_infoframe,
.hdmi_write_hdmi_infoframe = it6263_hdmi_write_hdmi_infoframe,
};

static int it6263_probe(struct i2c_client *client)
Expand Down
Loading