diff options
Diffstat (limited to 'sound/soc/sh/rcar/adg.c')
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 151 |
1 files changed, 107 insertions, 44 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 9430097979a5..a53235c4d1b0 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -19,8 +19,8 @@ | |||
19 | struct rsnd_adg { | 19 | struct rsnd_adg { |
20 | struct clk *clk[CLKMAX]; | 20 | struct clk *clk[CLKMAX]; |
21 | 21 | ||
22 | int rate_of_441khz_div_6; | 22 | int rbga_rate_for_441khz_div_6; /* RBGA */ |
23 | int rate_of_48khz_div_6; | 23 | int rbgb_rate_for_48khz_div_6; /* RBGB */ |
24 | u32 ckr; | 24 | u32 ckr; |
25 | }; | 25 | }; |
26 | 26 | ||
@@ -30,41 +30,114 @@ struct rsnd_adg { | |||
30 | i++, (pos) = adg->clk[i]) | 30 | i++, (pos) = adg->clk[i]) |
31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | 31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) |
32 | 32 | ||
33 | static enum rsnd_reg rsnd_adg_ssi_reg_get(int id) | 33 | static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, |
34 | struct rsnd_mod *mod, | ||
35 | unsigned int src_rate, | ||
36 | unsigned int dst_rate) | ||
34 | { | 37 | { |
35 | enum rsnd_reg reg; | 38 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
39 | struct device *dev = rsnd_priv_to_dev(priv); | ||
40 | int idx, sel, div, shift; | ||
41 | u32 mask, val; | ||
42 | int id = rsnd_mod_id(mod); | ||
43 | unsigned int sel_rate [] = { | ||
44 | clk_get_rate(adg->clk[CLKA]), /* 000: CLKA */ | ||
45 | clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */ | ||
46 | clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */ | ||
47 | 0, /* 011: MLBCLK (not used) */ | ||
48 | adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */ | ||
49 | adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */ | ||
50 | }; | ||
51 | |||
52 | /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */ | ||
53 | for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { | ||
54 | for (div = 128, idx = 0; | ||
55 | div <= 2048; | ||
56 | div *= 2, idx++) { | ||
57 | if (src_rate == sel_rate[sel] / div) { | ||
58 | val = (idx << 4) | sel; | ||
59 | goto find_rate; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | dev_err(dev, "can't find convert src clk\n"); | ||
64 | return -EINVAL; | ||
65 | |||
66 | find_rate: | ||
67 | shift = (id % 4) * 8; | ||
68 | mask = 0xFF << shift; | ||
69 | val = val << shift; | ||
70 | |||
71 | dev_dbg(dev, "adg convert src clk = %02x\n", val); | ||
72 | |||
73 | switch (id / 4) { | ||
74 | case 0: | ||
75 | rsnd_mod_bset(mod, AUDIO_CLK_SEL3, mask, val); | ||
76 | break; | ||
77 | case 1: | ||
78 | rsnd_mod_bset(mod, AUDIO_CLK_SEL4, mask, val); | ||
79 | break; | ||
80 | case 2: | ||
81 | rsnd_mod_bset(mod, AUDIO_CLK_SEL5, mask, val); | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Gen1 doesn't need dst_rate settings, | ||
87 | * since it uses SSI WS pin. | ||
88 | * see also rsnd_src_set_route_if_gen1() | ||
89 | */ | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, | ||
95 | struct rsnd_mod *mod, | ||
96 | unsigned int src_rate, | ||
97 | unsigned int dst_rate) | ||
98 | { | ||
99 | if (rsnd_is_gen1(priv)) | ||
100 | return rsnd_adg_set_convert_clk_gen1(priv, mod, | ||
101 | src_rate, dst_rate); | ||
102 | |||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) | ||
107 | { | ||
108 | int id = rsnd_mod_id(mod); | ||
109 | int shift = (id % 4) * 8; | ||
110 | u32 mask = 0xFF << shift; | ||
111 | |||
112 | val = val << shift; | ||
36 | 113 | ||
37 | /* | 114 | /* |
38 | * SSI 8 is not connected to ADG. | 115 | * SSI 8 is not connected to ADG. |
39 | * it works with SSI 7 | 116 | * it works with SSI 7 |
40 | */ | 117 | */ |
41 | if (id == 8) | 118 | if (id == 8) |
42 | return RSND_REG_MAX; | 119 | return; |
43 | 120 | ||
44 | if (0 <= id && id <= 3) | 121 | switch (id / 4) { |
45 | reg = RSND_REG_AUDIO_CLK_SEL0; | 122 | case 0: |
46 | else if (4 <= id && id <= 7) | 123 | rsnd_mod_bset(mod, AUDIO_CLK_SEL0, mask, val); |
47 | reg = RSND_REG_AUDIO_CLK_SEL1; | 124 | break; |
48 | else | 125 | case 1: |
49 | reg = RSND_REG_AUDIO_CLK_SEL2; | 126 | rsnd_mod_bset(mod, AUDIO_CLK_SEL1, mask, val); |
50 | 127 | break; | |
51 | return reg; | 128 | case 2: |
129 | rsnd_mod_bset(mod, AUDIO_CLK_SEL2, mask, val); | ||
130 | break; | ||
131 | } | ||
52 | } | 132 | } |
53 | 133 | ||
54 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) | 134 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) |
55 | { | 135 | { |
56 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
57 | enum rsnd_reg reg; | ||
58 | int id; | ||
59 | |||
60 | /* | 136 | /* |
61 | * "mod" = "ssi" here. | 137 | * "mod" = "ssi" here. |
62 | * we can get "ssi id" from mod | 138 | * we can get "ssi id" from mod |
63 | */ | 139 | */ |
64 | id = rsnd_mod_id(mod); | 140 | rsnd_adg_set_ssi_clk(mod, 0); |
65 | reg = rsnd_adg_ssi_reg_get(id); | ||
66 | |||
67 | rsnd_write(priv, mod, reg, 0); | ||
68 | 141 | ||
69 | return 0; | 142 | return 0; |
70 | } | 143 | } |
@@ -75,8 +148,7 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) | |||
75 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | 148 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
76 | struct device *dev = rsnd_priv_to_dev(priv); | 149 | struct device *dev = rsnd_priv_to_dev(priv); |
77 | struct clk *clk; | 150 | struct clk *clk; |
78 | enum rsnd_reg reg; | 151 | int i; |
79 | int id, shift, i; | ||
80 | u32 data; | 152 | u32 data; |
81 | int sel_table[] = { | 153 | int sel_table[] = { |
82 | [CLKA] = 0x1, | 154 | [CLKA] = 0x1, |
@@ -102,12 +174,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) | |||
102 | /* | 174 | /* |
103 | * find 1/6 clock from BRGA/BRGB | 175 | * find 1/6 clock from BRGA/BRGB |
104 | */ | 176 | */ |
105 | if (rate == adg->rate_of_441khz_div_6) { | 177 | if (rate == adg->rbga_rate_for_441khz_div_6) { |
106 | data = 0x10; | 178 | data = 0x10; |
107 | goto found_clock; | 179 | goto found_clock; |
108 | } | 180 | } |
109 | 181 | ||
110 | if (rate == adg->rate_of_48khz_div_6) { | 182 | if (rate == adg->rbgb_rate_for_48khz_div_6) { |
111 | data = 0x20; | 183 | data = 0x20; |
112 | goto found_clock; | 184 | goto found_clock; |
113 | } | 185 | } |
@@ -125,19 +197,10 @@ found_clock: | |||
125 | * This "mod" = "ssi" here. | 197 | * This "mod" = "ssi" here. |
126 | * we can get "ssi id" from mod | 198 | * we can get "ssi id" from mod |
127 | */ | 199 | */ |
128 | id = rsnd_mod_id(mod); | 200 | rsnd_adg_set_ssi_clk(mod, data); |
129 | reg = rsnd_adg_ssi_reg_get(id); | ||
130 | |||
131 | dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate); | ||
132 | |||
133 | /* | ||
134 | * Enable SSIx clock | ||
135 | */ | ||
136 | shift = (id % 4) * 8; | ||
137 | 201 | ||
138 | rsnd_bset(priv, mod, reg, | 202 | dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", |
139 | 0xFF << shift, | 203 | rsnd_mod_id(mod), i, rate); |
140 | data << shift); | ||
141 | 204 | ||
142 | return 0; | 205 | return 0; |
143 | } | 206 | } |
@@ -166,8 +229,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
166 | * rsnd_adg_ssi_clk_try_start() | 229 | * rsnd_adg_ssi_clk_try_start() |
167 | */ | 230 | */ |
168 | ckr = 0; | 231 | ckr = 0; |
169 | adg->rate_of_441khz_div_6 = 0; | 232 | adg->rbga_rate_for_441khz_div_6 = 0; |
170 | adg->rate_of_48khz_div_6 = 0; | 233 | adg->rbgb_rate_for_48khz_div_6 = 0; |
171 | for_each_rsnd_clk(clk, adg, i) { | 234 | for_each_rsnd_clk(clk, adg, i) { |
172 | rate = clk_get_rate(clk); | 235 | rate = clk_get_rate(clk); |
173 | 236 | ||
@@ -175,14 +238,14 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
175 | continue; | 238 | continue; |
176 | 239 | ||
177 | /* RBGA */ | 240 | /* RBGA */ |
178 | if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) { | 241 | if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) { |
179 | adg->rate_of_441khz_div_6 = rate / 6; | 242 | adg->rbga_rate_for_441khz_div_6 = rate / 6; |
180 | ckr |= brg_table[i] << 20; | 243 | ckr |= brg_table[i] << 20; |
181 | } | 244 | } |
182 | 245 | ||
183 | /* RBGB */ | 246 | /* RBGB */ |
184 | if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) { | 247 | if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) { |
185 | adg->rate_of_48khz_div_6 = rate / 6; | 248 | adg->rbgb_rate_for_48khz_div_6 = rate / 6; |
186 | ckr |= brg_table[i] << 16; | 249 | ckr |= brg_table[i] << 16; |
187 | } | 250 | } |
188 | } | 251 | } |