4 * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
12 #define MIX_NAME_SIZE 16
13 #define MIX_NAME "mix"
16 struct rsnd_mix_platform_info
*info
; /* rcar_snd.h */
20 #define rsnd_mix_nr(priv) ((priv)->mix_nr)
21 #define for_each_rsnd_mix(pos, priv, i) \
23 ((i) < rsnd_mix_nr(priv)) && \
24 ((pos) = (struct rsnd_mix *)(priv)->mix + i); \
28 static void rsnd_mix_soft_reset(struct rsnd_mod
*mod
)
30 rsnd_mod_write(mod
, MIX_SWRSR
, 0);
31 rsnd_mod_write(mod
, MIX_SWRSR
, 1);
34 #define rsnd_mix_initialize_lock(mod) __rsnd_mix_initialize_lock(mod, 1)
35 #define rsnd_mix_initialize_unlock(mod) __rsnd_mix_initialize_lock(mod, 0)
36 static void __rsnd_mix_initialize_lock(struct rsnd_mod
*mod
, u32 enable
)
38 rsnd_mod_write(mod
, MIX_MIXIR
, enable
);
41 static void rsnd_mix_volume_update(struct rsnd_dai_stream
*io
,
45 /* Disable MIX dB setting */
46 rsnd_mod_write(mod
, MIX_MDBER
, 0);
48 rsnd_mod_write(mod
, MIX_MDBAR
, 0);
49 rsnd_mod_write(mod
, MIX_MDBBR
, 0);
50 rsnd_mod_write(mod
, MIX_MDBCR
, 0);
51 rsnd_mod_write(mod
, MIX_MDBDR
, 0);
53 /* Enable MIX dB setting */
54 rsnd_mod_write(mod
, MIX_MDBER
, 1);
57 static int rsnd_mix_init(struct rsnd_mod
*mod
,
58 struct rsnd_dai_stream
*io
,
59 struct rsnd_priv
*priv
)
61 rsnd_mod_power_on(mod
);
63 rsnd_mix_soft_reset(mod
);
65 rsnd_mix_initialize_lock(mod
);
67 rsnd_mod_write(mod
, MIX_ADINR
, rsnd_get_adinr_chan(mod
, io
));
69 rsnd_path_parse(priv
, io
);
72 rsnd_mod_write(mod
, MIX_MIXMR
, 0);
73 rsnd_mod_write(mod
, MIX_MVPDR
, 0);
75 rsnd_mix_volume_update(io
, mod
);
77 rsnd_mix_initialize_unlock(mod
);
82 static int rsnd_mix_quit(struct rsnd_mod
*mod
,
83 struct rsnd_dai_stream
*io
,
84 struct rsnd_priv
*priv
)
86 rsnd_mod_power_off(mod
);
91 static struct rsnd_mod_ops rsnd_mix_ops
= {
93 .init
= rsnd_mix_init
,
94 .quit
= rsnd_mix_quit
,
97 struct rsnd_mod
*rsnd_mix_mod_get(struct rsnd_priv
*priv
, int id
)
99 if (WARN_ON(id
< 0 || id
>= rsnd_mix_nr(priv
)))
102 return rsnd_mod_get((struct rsnd_mix
*)(priv
->mix
) + id
);
105 static void rsnd_of_parse_mix(struct platform_device
*pdev
,
106 const struct rsnd_of_data
*of_data
,
107 struct rsnd_priv
*priv
)
109 struct device_node
*node
;
110 struct rsnd_mix_platform_info
*mix_info
;
111 struct rcar_snd_info
*info
= rsnd_priv_to_info(priv
);
112 struct device
*dev
= &pdev
->dev
;
118 node
= of_get_child_by_name(dev
->of_node
, "rcar_sound,mix");
122 nr
= of_get_child_count(node
);
124 goto rsnd_of_parse_mix_end
;
126 mix_info
= devm_kzalloc(dev
,
127 sizeof(struct rsnd_mix_platform_info
) * nr
,
130 dev_err(dev
, "mix info allocation error\n");
131 goto rsnd_of_parse_mix_end
;
134 info
->mix_info
= mix_info
;
135 info
->mix_info_nr
= nr
;
137 rsnd_of_parse_mix_end
:
142 int rsnd_mix_probe(struct platform_device
*pdev
,
143 const struct rsnd_of_data
*of_data
,
144 struct rsnd_priv
*priv
)
146 struct rcar_snd_info
*info
= rsnd_priv_to_info(priv
);
147 struct device
*dev
= rsnd_priv_to_dev(priv
);
148 struct rsnd_mix
*mix
;
150 char name
[MIX_NAME_SIZE
];
153 /* This driver doesn't support Gen1 at this point */
154 if (rsnd_is_gen1(priv
))
157 rsnd_of_parse_mix(pdev
, of_data
, priv
);
159 nr
= info
->mix_info_nr
;
163 mix
= devm_kzalloc(dev
, sizeof(*mix
) * nr
, GFP_KERNEL
);
170 for_each_rsnd_mix(mix
, priv
, i
) {
171 snprintf(name
, MIX_NAME_SIZE
, "%s.%d",
174 clk
= devm_clk_get(dev
, name
);
178 mix
->info
= &info
->mix_info
[i
];
180 ret
= rsnd_mod_init(priv
, rsnd_mod_get(mix
), &rsnd_mix_ops
,
181 clk
, RSND_MOD_MIX
, i
);
189 void rsnd_mix_remove(struct platform_device
*pdev
,
190 struct rsnd_priv
*priv
)
192 struct rsnd_mix
*mix
;
195 for_each_rsnd_mix(mix
, priv
, i
) {
196 rsnd_mod_quit(rsnd_mod_get(mix
));