• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/media/stream_input/amports/adec.c
3  *
4  * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
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 as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17 
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/errno.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23 #include <linux/uio_driver.h>
24 #include <linux/amlogic/media/utils/aformat.h>
25 #include <linux/amlogic/media/frame_sync/ptsserv.h>
26 #include <linux/amlogic/media/registers/register.h>
27 #include <linux/amlogic/media/codec_mm/configs.h>
28 #include "../amports/streambuf.h"
29 #include <linux/module.h>
30 #include <linux/of.h>
31 #include "amports_priv.h"
32 #include "../../common/chips/decoder_cpu_ver_info.h"
33 #define INFO_VALID ((astream_dev) && (astream_dev->format))
34 
35 struct astream_device_s {
36 	char *name;
37 	char *format;
38 	s32 channum;
39 	s32 samplerate;
40 	s32 datawidth;
41 	int offset;
42 
43 	struct device dev;
44 };
45 
46 static char *astream_format[] = {
47 	"amadec_mpeg",
48 	"amadec_pcm_s16le",
49 	"amadec_aac",
50 	"amadec_ac3",
51 	"amadec_alaw",
52 	"amadec_mulaw",
53 	"amadec_dts",
54 	"amadec_pcm_s16be",
55 	"amadec_flac",
56 	"amadec_cook",
57 	"amadec_pcm_u8",
58 	"amadec_adpcm",
59 	"amadec_amr",
60 	"amadec_raac",
61 	"amadec_wma",
62 	"amadec_wmapro",
63 	"amadec_pcm_bluray",
64 	"amadec_alac",
65 	"amadec_vorbis",
66 	"amadec_aac_latm",
67 	"amadec_ape",
68 	"amadec_eac3",
69 	"amadec_pcm_widi",
70 	"amadec_dra",
71 	"amadec_sipr",
72 	"amadec_truehd",
73 	"amadec_mpeg1",
74 	"amadec_mpeg2",
75 	"amadec_wmavoi",
76 	"amadec_wmalossless",
77 	"amadec_pcm_s24le",
78 	"adec_max"
79 };
80 
81 static const char *na_string = "NA";
82 static struct astream_device_s *astream_dev;
83 
format_show(struct class * class,struct class_attribute * attr,char * buf)84 static ssize_t format_show(struct class *class, struct class_attribute *attr,
85 						   char *buf)
86 {
87 	if (INFO_VALID && astream_dev->format)
88 		return sprintf(buf, "%s\n", astream_dev->format);
89 	else
90 		return sprintf(buf, "%s\n", na_string);
91 }
92 
channum_show(struct class * class,struct class_attribute * attr,char * buf)93 static ssize_t channum_show(struct class *class, struct class_attribute *attr,
94 							char *buf)
95 {
96 	if (INFO_VALID)
97 		return sprintf(buf, "%u\n", astream_dev->channum);
98 	else
99 		return sprintf(buf, "%s\n", na_string);
100 }
101 
samplerate_show(struct class * class,struct class_attribute * attr,char * buf)102 static ssize_t samplerate_show(struct class *class,
103 				struct class_attribute *attr, char *buf)
104 {
105 	if (INFO_VALID)
106 		return sprintf(buf, "%u\n", astream_dev->samplerate);
107 	else
108 		return sprintf(buf, "%s\n", na_string);
109 }
110 
datawidth_show(struct class * class,struct class_attribute * attr,char * buf)111 static ssize_t datawidth_show(struct class *class,
112 				struct class_attribute *attr,
113 					char *buf)
114 {
115 	if (INFO_VALID)
116 		return sprintf(buf, "%u\n", astream_dev->datawidth);
117 	else
118 		return sprintf(buf, "%s\n", na_string);
119 }
120 
pts_show(struct class * class,struct class_attribute * attr,char * buf)121 static ssize_t pts_show(struct class *class, struct class_attribute *attr,
122 						char *buf)
123 {
124 	u32 pts, frame_size;
125 	u32 pts_margin = 0;
126 
127 	if (astream_dev->samplerate <= 12000)
128 		pts_margin = 512;
129 
130 	if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts,
131 			&frame_size, pts_margin) >= 0))
132 		return sprintf(buf, "0x%x\n", pts);
133 	else
134 		return sprintf(buf, "%s\n", na_string);
135 }
136 
addr_offset_show(struct class * class,struct class_attribute * attr,char * buf)137 static ssize_t addr_offset_show(struct class *class,
138 				struct class_attribute *attr, char *buf)
139 {
140 	return sprintf(buf, "%d\n", astream_dev->offset);
141 }
142 
143 static struct class_attribute astream_class_attrs[] = {
144 	__ATTR_RO(format),
145 	__ATTR_RO(samplerate),
146 	__ATTR_RO(channum),
147 	__ATTR_RO(datawidth),
148 	__ATTR_RO(pts),
149 	__ATTR_RO(addr_offset),
150 	__ATTR_NULL
151 };
152 
153 static struct class astream_class = {
154 		.name = "astream",
155 		.class_attrs = astream_class_attrs,
156 	};
157 
158 #if 1
159 #define IO_CBUS_PHY_BASE 0xc1100000ULL
160 #define IO_AOBUS_PHY_BASE 0xc8100000ULL
161 #define CBUS_REG_OFFSET(reg) ((reg) << 2)
162 #define IO_SECBUS_PHY_BASE 0xda000000ULL
163 
164 
165 #define IO_AOBUS_PHY_BASE_AFTER_G12A 0xff800000ULL
166 
167 static struct uio_info astream_uio_info = {
168 	.name = "astream_uio",
169 	.version = "0.1",
170 	.irq = UIO_IRQ_NONE,
171 
172 	.mem = {
173 		[0] = {
174 			.name = "AIFIFO",
175 			.memtype = UIO_MEM_PHYS,
176 			.addr =
177 			(IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL))
178 			&(PAGE_MASK),
179 			.size = PAGE_SIZE,
180 		},
181 		[1] = {
182 			.memtype = UIO_MEM_PHYS,
183 			.addr =
184 			(IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(VCOP_CTRL_REG)),
185 			.size = PAGE_SIZE,
186 		},
187 /*
188 		[2] = {
189 			.name = "SECBUS",
190 			.memtype = UIO_MEM_PHYS,
191 			.addr = (IO_SECBUS_PHY_BASE),
192 			.size = PAGE_SIZE,
193 		},
194 */
195 		[2] = {
196 			.name = "CBUS",
197 			.memtype = UIO_MEM_PHYS,
198 			.addr =
199 			(IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(ASSIST_HW_REV))
200 			&(PAGE_MASK),
201 			.size = PAGE_SIZE,
202 		},
203 		[3] = {
204 			.name = "CBUS-START",
205 			.memtype = UIO_MEM_PHYS,
206 			.addr = (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(0x1000)),
207 			.size = PAGE_SIZE,
208 		},
209 		[4] = {
210 			.name = "AOBUS-START",
211 			.memtype = UIO_MEM_PHYS,
212 			.addr = (IO_AOBUS_PHY_BASE),
213 			.size = PAGE_SIZE,
214 		},
215 	},
216 };
217 #endif
218 
astream_release(struct device * dev)219 static void astream_release(struct device *dev)
220 {
221 	kfree(astream_dev);
222 
223 	astream_dev = NULL;
224 }
225 
adec_init(struct stream_port_s * port)226 s32 adec_init(struct stream_port_s *port)
227 {
228 	enum aformat_e af;
229 
230 	if (!astream_dev)
231 		return -ENODEV;
232 
233 	af = port->aformat;
234 
235 	astream_dev->channum = port->achanl;
236 	astream_dev->samplerate = port->asamprate;
237 	astream_dev->datawidth = port->adatawidth;
238 
239 	/*wmb();don't need it...*/
240 	if (af < ARRAY_SIZE(astream_format))
241 		astream_dev->format = astream_format[af];
242 	else
243 		astream_dev->format = NULL;
244 	return 0;
245 }
246 EXPORT_SYMBOL(adec_init);
247 
adec_release(enum aformat_e vf)248 s32 adec_release(enum aformat_e vf)
249 {
250 	pr_info("adec_release\n");
251 
252 	if (!astream_dev)
253 		return -ENODEV;
254 
255 	astream_dev->format = NULL;
256 
257 	return 0;
258 }
259 EXPORT_SYMBOL(adec_release);
260 
amstream_adec_show_fun(const char * trigger,int id,char * sbuf,int size)261 int amstream_adec_show_fun(const char *trigger, int id, char *sbuf, int size)
262 {
263 	int ret = -1;
264 	void *buf, *getbuf = NULL;
265 	if (size < PAGE_SIZE) {
266 		getbuf = (void *)__get_free_page(GFP_KERNEL);
267 		if (!getbuf)
268 			return -ENOMEM;
269 		buf = getbuf;
270 	} else {
271 		buf = sbuf;
272 	}
273 	switch (trigger[0]) {
274 	case 'f':
275 		ret =  format_show(NULL, NULL, buf);
276 		break;
277 	case 's':
278 		ret =  samplerate_show(NULL, NULL, buf);
279 		break;
280 	case 'c':
281 		ret =  channum_show(NULL, NULL, buf);
282 		break;
283 	case 'd':
284 		ret =  datawidth_show(NULL, NULL, buf);
285 		break;
286 	case 'p':
287 		ret =  pts_show(NULL, NULL, buf);
288 		break;
289 	default:
290 		ret = -1;
291 	}
292 	if (ret > 0 && getbuf != NULL) {
293 		ret = min_t(int, ret, size);
294 		strncpy(sbuf, buf, ret);
295 	}
296 	if (getbuf != NULL)
297 		free_page((unsigned long)getbuf);
298 	return ret;
299 }
300 
301 static struct mconfig adec_configs[] = {
302 	MC_FUN("format", &amstream_adec_show_fun, NULL),
303 	MC_FUN("samplerate", &amstream_adec_show_fun, NULL),
304 	MC_FUN("channum", &amstream_adec_show_fun, NULL),
305 	MC_FUN("datawidth", &amstream_adec_show_fun, NULL),
306 	MC_FUN("pts", &amstream_adec_show_fun, NULL),
307 };
308 static struct mconfig_node adec_node;
309 
310 
astream_dev_register(void)311 s32 astream_dev_register(void)
312 {
313 	s32 r;
314 	struct device_node *node;
315 	unsigned int cbus_base = 0xffd00000;
316 
317 	r = class_register(&astream_class);
318 	if (r) {
319 		pr_info("astream class create fail.\n");
320 		return r;
321 	}
322 
323 	astream_dev = kzalloc(sizeof(struct astream_device_s), GFP_KERNEL);
324 
325 	if (!astream_dev) {
326 		pr_info("astream device create fail.\n");
327 		r = -ENOMEM;
328 		goto err_3;
329 	}
330 
331 	astream_dev->dev.class = &astream_class;
332 	astream_dev->dev.release = astream_release;
333 	astream_dev->offset = 0;
334 	dev_set_name(&astream_dev->dev, "astream-dev");
335 
336 	dev_set_drvdata(&astream_dev->dev, astream_dev);
337 
338 	r = device_register(&astream_dev->dev);
339 	if (r) {
340 		pr_info("astream device register fail.\n");
341 		goto err_2;
342 	}
343 
344 	if (AM_MESON_CPU_MAJOR_ID_TXL < get_cpu_major_id()
345 		&& MESON_CPU_MAJOR_ID_GXLX != get_cpu_type()) {
346 		node = of_find_node_by_path("/codec_io/io_cbus_base");
347 		if (!node) {
348 			pr_info("No io_cbus_base node found.");
349 			goto err_1;
350 		}
351 
352 #ifdef CONFIG_ARM64_A32
353 		r = of_property_read_u32_index(node, "reg", 0, &cbus_base);
354 #else
355 		r = of_property_read_u32_index(node, "reg", 1, &cbus_base);
356 #endif
357 		if (r) {
358 			pr_info("No find node.\n");
359 			goto err_1;
360 		}
361 
362 		/*need to offset -0x100 in txlx.*/
363 		astream_dev->offset = -0x100;
364 
365 		/*need to offset -0x180 in g12a.*/
366 		if (AM_MESON_CPU_MAJOR_ID_G12A <= get_cpu_major_id()) {
367 			astream_dev->offset = -0x180;
368 			/* after G12A chip, the aobus base addr changed */
369 			astream_uio_info.mem[4].addr = IO_AOBUS_PHY_BASE_AFTER_G12A;
370 		}
371 		astream_uio_info.mem[0].addr =
372 			(cbus_base + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL +
373 			astream_dev->offset)) & (PAGE_MASK);
374 
375 		astream_uio_info.mem[3].addr =
376 			(cbus_base + CBUS_REG_OFFSET(ASSIST_HW_REV +
377 			0x100)) & (PAGE_MASK);
378 	}
379 
380 #if 1
381 	if (uio_register_device(&astream_dev->dev, &astream_uio_info)) {
382 		pr_info("astream UIO device register fail.\n");
383 		r = -ENODEV;
384 		goto err_1;
385 	}
386 #endif
387 	INIT_REG_NODE_CONFIGS("media", &adec_node,
388 		"adec", adec_configs, CONFIG_FOR_R);
389 	return 0;
390 
391 err_1:
392 	device_unregister(&astream_dev->dev);
393 
394 err_2:
395 	kfree(astream_dev);
396 	astream_dev = NULL;
397 
398 err_3:
399 	class_unregister(&astream_class);
400 
401 	return r;
402 }
403 
astream_dev_unregister(void)404 void astream_dev_unregister(void)
405 {
406 	if (astream_dev) {
407 #if 1
408 		uio_unregister_device(&astream_uio_info);
409 #endif
410 
411 		device_unregister(&astream_dev->dev);
412 
413 		class_unregister(&astream_class);
414 	}
415 }
416