diff options
author | Andy Green <andy.green@linaro.org> | 2015-11-21 10:17:52 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2015-12-08 07:11:31 +0800 |
commit | 8e4b592f7a18aa15c9f6f573696a90b4f8c5193a (patch) | |
tree | ea7f9f53dda57d646398d525dd904b3d527b175b | |
parent | 008ee0fe8e44694a305bbd05094090566120702e (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.c | 90 | ||||
-rw-r--r-- | drivers/gpu/drm/i2c/adv7511.h | 2 |
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; |