ctu.c (d1208404dd477c142680437137c9996b95bfd508) | ctu.c (5ba17b42e1755c3c5cfe96370cfd47f34d01f62c) |
---|---|
1/* 2 * ctu.c 3 * 4 * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 5 * 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. 9 */ 10#include "rsnd.h" 11 12#define CTU_NAME_SIZE 16 13#define CTU_NAME "ctu" 14 15struct rsnd_ctu { | 1/* 2 * ctu.c 3 * 4 * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 5 * 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. 9 */ 10#include "rsnd.h" 11 12#define CTU_NAME_SIZE 16 13#define CTU_NAME "ctu" 14 15struct rsnd_ctu { |
16 struct rsnd_ctu_platform_info *info; /* rcar_snd.h */ | |
17 struct rsnd_mod mod; 18}; 19 20#define rsnd_ctu_nr(priv) ((priv)->ctu_nr) 21#define for_each_rsnd_ctu(pos, priv, i) \ 22 for ((i) = 0; \ 23 ((i) < rsnd_ctu_nr(priv)) && \ 24 ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \ 25 i++) 26 | 16 struct rsnd_mod mod; 17}; 18 19#define rsnd_ctu_nr(priv) ((priv)->ctu_nr) 20#define for_each_rsnd_ctu(pos, priv, i) \ 21 for ((i) = 0; \ 22 ((i) < rsnd_ctu_nr(priv)) && \ 23 ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \ 24 i++) 25 |
26#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id) |
|
27#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) 28#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) 29static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) 30{ 31 rsnd_mod_write(mod, CTU_CTUIR, enable); 32} 33 | 27#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) 28#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) 29static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) 30{ 31 rsnd_mod_write(mod, CTU_CTUIR, enable); 32} 33 |
34static int rsnd_ctu_probe_(struct rsnd_mod *mod, 35 struct rsnd_dai_stream *io, 36 struct rsnd_priv *priv) 37{ 38 return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4); 39} 40 |
|
34static int rsnd_ctu_init(struct rsnd_mod *mod, 35 struct rsnd_dai_stream *io, 36 struct rsnd_priv *priv) 37{ 38 rsnd_mod_power_on(mod); 39 40 rsnd_ctu_initialize_lock(mod); 41 --- 10 unchanged lines hidden (view full) --- 52{ 53 rsnd_mod_power_off(mod); 54 55 return 0; 56} 57 58static struct rsnd_mod_ops rsnd_ctu_ops = { 59 .name = CTU_NAME, | 41static int rsnd_ctu_init(struct rsnd_mod *mod, 42 struct rsnd_dai_stream *io, 43 struct rsnd_priv *priv) 44{ 45 rsnd_mod_power_on(mod); 46 47 rsnd_ctu_initialize_lock(mod); 48 --- 10 unchanged lines hidden (view full) --- 59{ 60 rsnd_mod_power_off(mod); 61 62 return 0; 63} 64 65static struct rsnd_mod_ops rsnd_ctu_ops = { 66 .name = CTU_NAME, |
67 .probe = rsnd_ctu_probe_, |
|
60 .init = rsnd_ctu_init, 61 .quit = rsnd_ctu_quit, 62}; 63 64struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) 65{ 66 if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv))) 67 id = 0; 68 | 68 .init = rsnd_ctu_init, 69 .quit = rsnd_ctu_quit, 70}; 71 72struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) 73{ 74 if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv))) 75 id = 0; 76 |
69 return rsnd_mod_get((struct rsnd_ctu *)(priv->ctu) + id); | 77 return rsnd_mod_get(rsnd_ctu_get(priv, id)); |
70} 71 | 78} 79 |
72static void rsnd_of_parse_ctu(struct platform_device *pdev, 73 const struct rsnd_of_data *of_data, 74 struct rsnd_priv *priv) | 80int rsnd_ctu_probe(struct rsnd_priv *priv) |
75{ 76 struct device_node *node; | 81{ 82 struct device_node *node; |
77 struct rsnd_ctu_platform_info *ctu_info; 78 struct rcar_snd_info *info = rsnd_priv_to_info(priv); 79 struct device *dev = &pdev->dev; 80 int nr; 81 82 if (!of_data) 83 return; 84 85 node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu"); 86 if (!node) 87 return; 88 89 nr = of_get_child_count(node); 90 if (!nr) 91 goto rsnd_of_parse_ctu_end; 92 93 ctu_info = devm_kzalloc(dev, 94 sizeof(struct rsnd_ctu_platform_info) * nr, 95 GFP_KERNEL); 96 if (!ctu_info) { 97 dev_err(dev, "ctu info allocation error\n"); 98 goto rsnd_of_parse_ctu_end; 99 } 100 101 info->ctu_info = ctu_info; 102 info->ctu_info_nr = nr; 103 104rsnd_of_parse_ctu_end: 105 of_node_put(node); 106 107} 108 109int rsnd_ctu_probe(struct platform_device *pdev, 110 const struct rsnd_of_data *of_data, 111 struct rsnd_priv *priv) 112{ 113 struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 83 struct device_node *np; |
114 struct device *dev = rsnd_priv_to_dev(priv); 115 struct rsnd_ctu *ctu; 116 struct clk *clk; 117 char name[CTU_NAME_SIZE]; 118 int i, nr, ret; 119 120 /* This driver doesn't support Gen1 at this point */ 121 if (rsnd_is_gen1(priv)) 122 return 0; 123 | 84 struct device *dev = rsnd_priv_to_dev(priv); 85 struct rsnd_ctu *ctu; 86 struct clk *clk; 87 char name[CTU_NAME_SIZE]; 88 int i, nr, ret; 89 90 /* This driver doesn't support Gen1 at this point */ 91 if (rsnd_is_gen1(priv)) 92 return 0; 93 |
124 rsnd_of_parse_ctu(pdev, of_data, priv); | 94 node = rsnd_ctu_of_node(priv); 95 if (!node) 96 return 0; /* not used is not error */ |
125 | 97 |
126 nr = info->ctu_info_nr; 127 if (!nr) 128 return 0; | 98 nr = of_get_child_count(node); 99 if (!nr) { 100 ret = -EINVAL; 101 goto rsnd_ctu_probe_done; 102 } |
129 130 ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL); | 103 104 ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL); |
131 if (!ctu) 132 return -ENOMEM; | 105 if (!ctu) { 106 ret = -ENOMEM; 107 goto rsnd_ctu_probe_done; 108 } |
133 134 priv->ctu_nr = nr; 135 priv->ctu = ctu; 136 | 109 110 priv->ctu_nr = nr; 111 priv->ctu = ctu; 112 |
137 for_each_rsnd_ctu(ctu, priv, i) { | 113 i = 0; 114 ret = 0; 115 for_each_child_of_node(node, np) { 116 ctu = rsnd_ctu_get(priv, i); 117 |
138 /* 139 * CTU00, CTU01, CTU02, CTU03 => CTU0 140 * CTU10, CTU11, CTU12, CTU13 => CTU1 141 */ 142 snprintf(name, CTU_NAME_SIZE, "%s.%d", 143 CTU_NAME, i / 4); 144 145 clk = devm_clk_get(dev, name); | 118 /* 119 * CTU00, CTU01, CTU02, CTU03 => CTU0 120 * CTU10, CTU11, CTU12, CTU13 => CTU1 121 */ 122 snprintf(name, CTU_NAME_SIZE, "%s.%d", 123 CTU_NAME, i / 4); 124 125 clk = devm_clk_get(dev, name); |
146 if (IS_ERR(clk)) 147 return PTR_ERR(clk); | 126 if (IS_ERR(clk)) { 127 ret = PTR_ERR(clk); 128 goto rsnd_ctu_probe_done; 129 } |
148 | 130 |
149 ctu->info = &info->ctu_info[i]; 150 | |
151 ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, | 131 ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, |
152 clk, RSND_MOD_CTU, i); | 132 clk, rsnd_mod_get_status, RSND_MOD_CTU, i); |
153 if (ret) | 133 if (ret) |
154 return ret; | 134 goto rsnd_ctu_probe_done; 135 136 i++; |
155 } 156 | 137 } 138 |
157 return 0; | 139 140rsnd_ctu_probe_done: 141 of_node_put(node); 142 143 return ret; |
158} 159 | 144} 145 |
160void rsnd_ctu_remove(struct platform_device *pdev, 161 struct rsnd_priv *priv) | 146void rsnd_ctu_remove(struct rsnd_priv *priv) |
162{ 163 struct rsnd_ctu *ctu; 164 int i; 165 166 for_each_rsnd_ctu(ctu, priv, i) { 167 rsnd_mod_quit(rsnd_mod_get(ctu)); 168 } 169} | 147{ 148 struct rsnd_ctu *ctu; 149 int i; 150 151 for_each_rsnd_ctu(ctu, priv, i) { 152 rsnd_mod_quit(rsnd_mod_get(ctu)); 153 } 154} |