summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2015-11-21 10:17:52 +0800
committerAndy Green <andy.green@linaro.org>2015-12-08 07:11:31 +0800
commit8e4b592f7a18aa15c9f6f573696a90b4f8c5193a (patch)
treeea7f9f53dda57d646398d525dd904b3d527b175b
parent008ee0fe8e44694a305bbd05094090566120702e (diff)
drm: adv7511 add 48kHz 2ch adio, packet and SPD
Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r--drivers/gpu/drm/i2c/adv7511.c90
-rw-r--r--drivers/gpu/drm/i2c/adv7511.h2
2 files changed, 91 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index 916964f85081..2a3db8de9ea8 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -161,6 +161,14 @@ static const struct regmap_config adv7533_cec_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_config adv7533_packet_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = 0xff,
+ .cache_type = REGCACHE_RBTREE,
+};
+
/* -----------------------------------------------------------------------------
* Hardware configuration
@@ -481,6 +489,72 @@ static void adv7511_dsi_receiver_dpms(struct adv7511 *adv7511)
regmap_update_bits(adv7511->regmap, 0x26, BIT(5), 0);
/* Black OFF */
regmap_write(adv7511->regmap, 0xd5, 0);
+
+ /* SPD */
+ {
+ static const unsigned char spd_if[] = {
+ 0x83, 0x01, 25, 0x00,
+ 'L', 'i', 'n', 'a', 'r', 'o', 0, 0,
+ '9', '6', 'b', 'o', 'a', 'r', 'd', 's',
+ ':', 'H', 'i', 'k', 'e', 'y', 0, 0,
+ };
+ int n;
+
+ for (n = 0; n < sizeof(spd_if); n++)
+ regmap_write(adv7511->regmap_packet, n, spd_if[n]);
+
+ /* enable send SPD */
+ regmap_update_bits(adv7511->regmap, 0x40, BIT(6), BIT(6));
+ }
+
+ /* force audio */
+ /* hide Audio infoframe updates */
+ regmap_update_bits(adv7511->regmap, 0x4a, BIT(5), BIT(5));
+
+ /* i2s, internal mclk, mclk-256 */
+ regmap_update_bits(adv7511->regmap, 0x0a, 0x1f, 1);
+ regmap_update_bits(adv7511->regmap, 0x0b, 0xe0, 0);
+ /* enable i2s, use i2s format, sample rate from i2s */
+ regmap_update_bits(adv7511->regmap, 0x0c, 0xc7, BIT(2));
+ /* 16 bit audio */
+ regmap_update_bits(adv7511->regmap, 0x0d, 0xff, 16);
+ /* 16-bit audio */
+ regmap_update_bits(adv7511->regmap, 0x14, 0x0f, 2 << 4);
+ /* 48kHz */
+ regmap_update_bits(adv7511->regmap, 0x15, 0xf0, 2 << 4);
+ /* enable N/CTS, enable Audio sample packets */
+ regmap_update_bits(adv7511->regmap, 0x44, BIT(5), BIT(5));
+ /* N = 6144 */
+ regmap_write(adv7511->regmap, 1, (6144 >> 16) & 0xf);
+ regmap_write(adv7511->regmap, 2, (6144 >> 8) & 0xff);
+ regmap_write(adv7511->regmap, 3, (6144) & 0xff);
+ /* automatic cts */
+ regmap_update_bits(adv7511->regmap, 0x0a, BIT(7), 0);
+ /* enable N/CTS */
+ regmap_update_bits(adv7511->regmap, 0x44, BIT(6), BIT(6));
+ /* not copyrighted */
+ regmap_update_bits(adv7511->regmap, 0x12, BIT(5), BIT(5));
+
+ /* left source */
+ regmap_update_bits(adv7511->regmap, 0x0e, 7 << 3, 0);
+ /* right source */
+ regmap_update_bits(adv7511->regmap, 0x0e, 7 << 0, 1);
+ /* number of channels: sect 4.5.4: set to 0 */
+ regmap_update_bits(adv7511->regmap, 0x73, 7, 1);
+ /* number of channels: sect 4.5.4: set to 0 */
+ regmap_update_bits(adv7511->regmap, 0x73, 0xf0, 1 << 4);
+ /* sample rate: 48kHz */
+ regmap_update_bits(adv7511->regmap, 0x74, 7 << 2, 3 << 2);
+ /* channel allocation reg: sect 4.5.4: set to 0 */
+ regmap_update_bits(adv7511->regmap, 0x76, 0xff, 0);
+ /* enable audio infoframes */
+ regmap_update_bits(adv7511->regmap, 0x44, BIT(3), BIT(3));
+
+ /* AV mute disable */
+ regmap_update_bits(adv7511->regmap, 0x4b, BIT(7) | BIT(6), BIT(7));
+
+ /* use Audio infoframe updated info */
+ regmap_update_bits(adv7511->regmap, 0x4a, BIT(5), 0);
} else {
/* Black ON */
regmap_write(adv7511->regmap, 0xd5, 1);
@@ -1248,9 +1322,14 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
adv7511_packet_disable(adv7511, 0xffff);
adv7511->i2c_main = i2c;
+
+ adv7511->i2c_packet = i2c_new_dummy(i2c->adapter, packet_i2c_addr >> 1);
+ if (!adv7511->i2c_packet)
+ return -ENOMEM;
+
adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
if (!adv7511->i2c_edid)
- return -ENOMEM;
+ goto err_i2c_unregister_packet;
adv7511->i2c_cec = i2c_new_dummy(i2c->adapter, cec_i2c_addr >> 1);
if (!adv7511->i2c_cec) {
@@ -1265,6 +1344,13 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
goto err_i2c_unregister_cec;
}
+ adv7511->regmap_packet = devm_regmap_init_i2c(adv7511->i2c_packet,
+ &adv7533_packet_regmap_config);
+ if (IS_ERR(adv7511->regmap_packet)) {
+ ret = PTR_ERR(adv7511->regmap_packet);
+ goto err_i2c_unregister_cec;
+ }
+
if (adv7511->type == ADV7533) {
ret = regmap_register_patch(adv7511->regmap_cec, adv7533_cec_fixed_registers,
ARRAY_SIZE(adv7533_cec_fixed_registers));
@@ -1303,6 +1389,8 @@ err_i2c_unregister_cec:
i2c_unregister_device(adv7511->i2c_cec);
err_i2c_unregister_edid:
i2c_unregister_device(adv7511->i2c_edid);
+err_i2c_unregister_packet:
+ i2c_unregister_device(adv7511->i2c_packet);
return ret;
}
diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h
index 26c9045f6b46..c0e4c395e051 100644
--- a/drivers/gpu/drm/i2c/adv7511.h
+++ b/drivers/gpu/drm/i2c/adv7511.h
@@ -248,11 +248,13 @@ struct adv7511 {
struct i2c_client *i2c_main;
struct i2c_client *i2c_edid;
struct i2c_client *i2c_cec;
+ struct i2c_client *i2c_packet;
int irq;
struct regmap *regmap;
struct regmap *regmap_cec;
+ struct regmap *regmap_packet;
enum drm_connector_status status;
bool powered;