Skip to content

Commit 7cb37b7

Browse files
V Sujith Kumar Reddybroonie
authored andcommitted
ASoC: qcom: Add support for lpass hdmi driver
Upadate lpass cpu and platform driver to support audio over dp. Also add lpass-hdmi.c and lpass-hdmi.h. Signed-off-by: V Sujith Kumar Reddy <[email protected]> Signed-off-by: Srinivasa Rao <[email protected]> Reviewed-by: Srinivas Kandagatla <[email protected]> Tested-by: Srinivas Kandagatla <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent d9e8e61 commit 7cb37b7

File tree

10 files changed

+1075
-97
lines changed

10 files changed

+1075
-97
lines changed

sound/soc/qcom/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ config SND_SOC_LPASS_CPU
1212
tristate
1313
select REGMAP_MMIO
1414

15+
config SND_SOC_LPASS_HDMI
16+
tristate
17+
select REGMAP_MMIO
18+
1519
config SND_SOC_LPASS_PLATFORM
1620
tristate
1721
select REGMAP_MMIO
@@ -30,6 +34,7 @@ config SND_SOC_LPASS_SC7180
3034
tristate
3135
select SND_SOC_LPASS_CPU
3236
select SND_SOC_LPASS_PLATFORM
37+
select SND_SOC_LPASS_HDMI
3338

3439
config SND_SOC_STORM
3540
tristate "ASoC I2S support for Storm boards"

sound/soc/qcom/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# SPDX-License-Identifier: GPL-2.0
22
# Platform
33
snd-soc-lpass-cpu-objs := lpass-cpu.o
4+
snd-soc-lpass-hdmi-objs := lpass-hdmi.o
45
snd-soc-lpass-platform-objs := lpass-platform.o
56
snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o
67
snd-soc-lpass-apq8016-objs := lpass-apq8016.o
78
snd-soc-lpass-sc7180-objs := lpass-sc7180.o
89

910
obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o
11+
obj-$(CONFIG_SND_SOC_LPASS_HDMI) += snd-soc-lpass-hdmi.o
1012
obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
1113
obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o
1214
obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o

sound/soc/qcom/lpass-apq8016.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = {
125125
};
126126

127127
static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata,
128-
int direction)
128+
int direction, unsigned int dai_id)
129129
{
130130
struct lpass_variant *v = drvdata->variant;
131131
int chan = 0;
@@ -151,7 +151,7 @@ static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata,
151151
return chan;
152152
}
153153

154-
static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
154+
static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id)
155155
{
156156
clear_bit(chan, &drvdata->dma_ch_bit_map);
157157

sound/soc/qcom/lpass-cpu.c

Lines changed: 241 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,206 @@ static struct regmap_config lpass_cpu_regmap_config = {
478478
.cache_type = REGCACHE_FLAT,
479479
};
480480

481+
static int lpass_hdmi_init_bitfields(struct device *dev, struct regmap *map)
482+
{
483+
struct lpass_data *drvdata = dev_get_drvdata(dev);
484+
struct lpass_variant *v = drvdata->variant;
485+
unsigned int i;
486+
struct lpass_hdmi_tx_ctl *tx_ctl;
487+
struct regmap_field *legacy_en;
488+
struct lpass_vbit_ctrl *vbit_ctl;
489+
struct regmap_field *tx_parity;
490+
struct lpass_dp_metadata_ctl *meta_ctl;
491+
struct lpass_sstream_ctl *sstream_ctl;
492+
struct regmap_field *ch_msb;
493+
struct regmap_field *ch_lsb;
494+
struct lpass_hdmitx_dmactl *tx_dmactl;
495+
int rval;
496+
497+
tx_ctl = devm_kzalloc(dev, sizeof(*tx_ctl), GFP_KERNEL);
498+
if (!tx_ctl)
499+
return -ENOMEM;
500+
501+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->soft_reset, tx_ctl->soft_reset);
502+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->force_reset, tx_ctl->force_reset);
503+
drvdata->tx_ctl = tx_ctl;
504+
505+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->legacy_en, legacy_en);
506+
drvdata->hdmitx_legacy_en = legacy_en;
507+
508+
vbit_ctl = devm_kzalloc(dev, sizeof(*vbit_ctl), GFP_KERNEL);
509+
if (!vbit_ctl)
510+
return -ENOMEM;
511+
512+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->replace_vbit, vbit_ctl->replace_vbit);
513+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->vbit_stream, vbit_ctl->vbit_stream);
514+
drvdata->vbit_ctl = vbit_ctl;
515+
516+
517+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->calc_en, tx_parity);
518+
drvdata->hdmitx_parity_calc_en = tx_parity;
519+
520+
meta_ctl = devm_kzalloc(dev, sizeof(*meta_ctl), GFP_KERNEL);
521+
if (!meta_ctl)
522+
return -ENOMEM;
523+
524+
rval = devm_regmap_field_bulk_alloc(dev, map, &meta_ctl->mute, &v->mute, 7);
525+
if (rval)
526+
return rval;
527+
drvdata->meta_ctl = meta_ctl;
528+
529+
sstream_ctl = devm_kzalloc(dev, sizeof(*sstream_ctl), GFP_KERNEL);
530+
if (!sstream_ctl)
531+
return -ENOMEM;
532+
533+
rval = devm_regmap_field_bulk_alloc(dev, map, &sstream_ctl->sstream_en, &v->sstream_en, 9);
534+
if (rval)
535+
return rval;
536+
537+
drvdata->sstream_ctl = sstream_ctl;
538+
539+
for (i = 0; i < LPASS_MAX_HDMI_DMA_CHANNELS; i++) {
540+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->msb_bits, ch_msb);
541+
drvdata->hdmitx_ch_msb[i] = ch_msb;
542+
543+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->lsb_bits, ch_lsb);
544+
drvdata->hdmitx_ch_lsb[i] = ch_lsb;
545+
546+
tx_dmactl = devm_kzalloc(dev, sizeof(*tx_dmactl), GFP_KERNEL);
547+
if (!tx_dmactl)
548+
return -ENOMEM;
549+
550+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->use_hw_chs, tx_dmactl->use_hw_chs);
551+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->use_hw_usr, tx_dmactl->use_hw_usr);
552+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->hw_chs_sel, tx_dmactl->hw_chs_sel);
553+
QCOM_REGMAP_FIELD_ALLOC(dev, map, v->hw_usr_sel, tx_dmactl->hw_usr_sel);
554+
drvdata->hdmi_tx_dmactl[i] = tx_dmactl;
555+
}
556+
return 0;
557+
}
558+
559+
static bool lpass_hdmi_regmap_writeable(struct device *dev, unsigned int reg)
560+
{
561+
struct lpass_data *drvdata = dev_get_drvdata(dev);
562+
struct lpass_variant *v = drvdata->variant;
563+
int i;
564+
565+
if (reg == LPASS_HDMI_TX_CTL_ADDR(v))
566+
return true;
567+
if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
568+
return true;
569+
if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
570+
return true;
571+
if (reg == LPASS_HDMI_TX_PARITY_ADDR(v))
572+
return true;
573+
if (reg == LPASS_HDMI_TX_DP_ADDR(v))
574+
return true;
575+
if (reg == LPASS_HDMI_TX_SSTREAM_ADDR(v))
576+
return true;
577+
if (reg == LPASS_HDMITX_APP_IRQEN_REG(v))
578+
return true;
579+
if (reg == LPASS_HDMITX_APP_IRQCLEAR_REG(v))
580+
return true;
581+
582+
for (i = 0; i < v->hdmi_rdma_channels; i++) {
583+
if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
584+
return true;
585+
if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
586+
return true;
587+
if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
588+
return true;
589+
}
590+
591+
for (i = 0; i < v->rdma_channels; ++i) {
592+
if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
593+
return true;
594+
if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
595+
return true;
596+
if (reg == LPAIF_HDMI_RDMABUFF_REG(v, i))
597+
return true;
598+
if (reg == LPAIF_HDMI_RDMAPER_REG(v, i))
599+
return true;
600+
}
601+
return false;
602+
}
603+
604+
static bool lpass_hdmi_regmap_readable(struct device *dev, unsigned int reg)
605+
{
606+
struct lpass_data *drvdata = dev_get_drvdata(dev);
607+
struct lpass_variant *v = drvdata->variant;
608+
int i;
609+
610+
if (reg == LPASS_HDMI_TX_CTL_ADDR(v))
611+
return true;
612+
if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
613+
return true;
614+
if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
615+
return true;
616+
617+
for (i = 0; i < v->hdmi_rdma_channels; i++) {
618+
if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
619+
return true;
620+
if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
621+
return true;
622+
if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
623+
return true;
624+
}
625+
626+
if (reg == LPASS_HDMI_TX_PARITY_ADDR(v))
627+
return true;
628+
if (reg == LPASS_HDMI_TX_DP_ADDR(v))
629+
return true;
630+
if (reg == LPASS_HDMI_TX_SSTREAM_ADDR(v))
631+
return true;
632+
if (reg == LPASS_HDMITX_APP_IRQEN_REG(v))
633+
return true;
634+
if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
635+
return true;
636+
637+
for (i = 0; i < v->rdma_channels; ++i) {
638+
if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
639+
return true;
640+
if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
641+
return true;
642+
if (reg == LPAIF_HDMI_RDMABUFF_REG(v, i))
643+
return true;
644+
if (reg == LPAIF_HDMI_RDMAPER_REG(v, i))
645+
return true;
646+
if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
647+
return true;
648+
}
649+
650+
return false;
651+
}
652+
653+
static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg)
654+
{
655+
struct lpass_data *drvdata = dev_get_drvdata(dev);
656+
struct lpass_variant *v = drvdata->variant;
657+
int i;
658+
659+
if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
660+
return true;
661+
if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
662+
return true;
663+
664+
for (i = 0; i < v->rdma_channels; ++i) {
665+
if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
666+
return true;
667+
}
668+
return false;
669+
}
670+
671+
struct regmap_config lpass_hdmi_regmap_config = {
672+
.reg_bits = 32,
673+
.reg_stride = 4,
674+
.val_bits = 32,
675+
.writeable_reg = lpass_hdmi_regmap_writeable,
676+
.readable_reg = lpass_hdmi_regmap_readable,
677+
.volatile_reg = lpass_hdmi_regmap_volatile,
678+
.cache_type = REGCACHE_FLAT,
679+
};
680+
481681
static unsigned int of_lpass_cpu_parse_sd_lines(struct device *dev,
482682
struct device_node *node,
483683
const char *name)
@@ -535,13 +735,17 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev,
535735
dev_err(dev, "valid dai id not found: %d\n", ret);
536736
continue;
537737
}
538-
539-
data->mi2s_playback_sd_mode[id] =
540-
of_lpass_cpu_parse_sd_lines(dev, node,
541-
"qcom,playback-sd-lines");
542-
data->mi2s_capture_sd_mode[id] =
543-
of_lpass_cpu_parse_sd_lines(dev, node,
738+
if (id == LPASS_DP_RX) {
739+
data->hdmi_port_enable = 1;
740+
dev_err(dev, "HDMI Port is enabled: %d\n", id);
741+
} else {
742+
data->mi2s_playback_sd_mode[id] =
743+
of_lpass_cpu_parse_sd_lines(dev, node,
744+
"qcom,playback-sd-lines");
745+
data->mi2s_capture_sd_mode[id] =
746+
of_lpass_cpu_parse_sd_lines(dev, node,
544747
"qcom,capture-sd-lines");
748+
}
545749
}
546750
}
547751

@@ -596,6 +800,27 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
596800
return PTR_ERR(drvdata->lpaif_map);
597801
}
598802

803+
if (drvdata->hdmi_port_enable) {
804+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-hdmiif");
805+
806+
drvdata->hdmiif = devm_ioremap_resource(dev, res);
807+
if (IS_ERR((void const __force *)drvdata->hdmiif)) {
808+
dev_err(dev, "error mapping reg resource: %ld\n",
809+
PTR_ERR((void const __force *)drvdata->hdmiif));
810+
return PTR_ERR((void const __force *)drvdata->hdmiif);
811+
}
812+
813+
lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant,
814+
variant->hdmi_rdma_channels);
815+
drvdata->hdmiif_map = devm_regmap_init_mmio(dev, drvdata->hdmiif,
816+
&lpass_hdmi_regmap_config);
817+
if (IS_ERR(drvdata->hdmiif_map)) {
818+
dev_err(dev, "error initializing regmap: %ld\n",
819+
PTR_ERR(drvdata->hdmiif_map));
820+
return PTR_ERR(drvdata->hdmiif_map);
821+
}
822+
}
823+
599824
if (variant->init) {
600825
ret = variant->init(pdev);
601826
if (ret) {
@@ -606,6 +831,9 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
606831

607832
for (i = 0; i < variant->num_dai; i++) {
608833
dai_id = variant->dai_driver[i].id;
834+
if (dai_id == LPASS_DP_RX)
835+
continue;
836+
609837
drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(dev,
610838
variant->dai_osr_clk_names[i]);
611839
if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) {
@@ -641,6 +869,13 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
641869
return ret;
642870
}
643871

872+
if (drvdata->hdmi_port_enable) {
873+
ret = lpass_hdmi_init_bitfields(dev, drvdata->hdmiif_map);
874+
if (ret) {
875+
dev_err(dev, "%s error hdmi init failed\n", __func__);
876+
return ret;
877+
}
878+
}
644879
ret = devm_snd_soc_register_component(dev,
645880
&lpass_cpu_comp_driver,
646881
variant->dai_driver,

0 commit comments

Comments
 (0)