summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/devices/platform-ipu-core.c
blob: fc4dd7cedc1189019dea590e8a4caa6b0ebf6884 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Copyright (C) 2011 Pengutronix
 * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the
 * Free Software Foundation.
 */
#include <linux/dma-mapping.h>

#include "../hardware.h"
#include "devices-common.h"

#define imx_ipu_core_entry_single(soc)					\
{									\
	.iobase = soc ## _IPU_CTRL_BASE_ADDR,				\
	.synirq = soc ## _INT_IPU_SYN,					\
	.errirq = soc ## _INT_IPU_ERR,					\
}

#ifdef CONFIG_SOC_IMX31
const struct imx_ipu_core_data imx31_ipu_core_data __initconst =
	imx_ipu_core_entry_single(MX31);
#endif

#ifdef CONFIG_SOC_IMX35
const struct imx_ipu_core_data imx35_ipu_core_data __initconst =
	imx_ipu_core_entry_single(MX35);
#endif

static struct platform_device *imx_ipu_coredev __initdata;

struct platform_device *__init imx_add_ipu_core(
		const struct imx_ipu_core_data *data)
{
	/* The resource order is important! */
	struct resource res[] = {
		{
			.start = data->iobase,
			.end = data->iobase + 0x5f,
			.flags = IORESOURCE_MEM,
		}, {
			.start = data->iobase + 0x88,
			.end = data->iobase + 0xb3,
			.flags = IORESOURCE_MEM,
		}, {
			.start = data->synirq,
			.end = data->synirq,
			.flags = IORESOURCE_IRQ,
		}, {
			.start = data->errirq,
			.end = data->errirq,
			.flags = IORESOURCE_IRQ,
		},
	};

	return imx_ipu_coredev = imx_add_platform_device("ipu-core", -1,
			res, ARRAY_SIZE(res), NULL, 0);
}

struct platform_device *__init imx_alloc_mx3_camera(
		const struct imx_ipu_core_data *data,
		const struct mx3_camera_pdata *pdata)
{
	struct resource res[] = {
		{
			.start = data->iobase + 0x60,
			.end = data->iobase + 0x87,
			.flags = IORESOURCE_MEM,
		},
	};
	int ret = -ENOMEM;
	struct platform_device *pdev;

	if (IS_ERR_OR_NULL(imx_ipu_coredev))
		return ERR_PTR(-ENODEV);

	pdev = platform_device_alloc("mx3-camera", 0);
	if (!pdev)
		goto err;

	pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
	if (!pdev->dev.dma_mask)
		goto err;

	*pdev->dev.dma_mask = DMA_BIT_MASK(32);
	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);

	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
	if (ret)
		goto err;

	if (pdata) {
		struct mx3_camera_pdata *copied_pdata;

		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
		if (ret) {
err:
			kfree(pdev->dev.dma_mask);
			platform_device_put(pdev);
			return ERR_PTR(-ENODEV);
		}
		copied_pdata = dev_get_platdata(&pdev->dev);
		copied_pdata->dma_dev = &imx_ipu_coredev->dev;
	}

	return pdev;
}

struct platform_device *__init imx_add_mx3_sdc_fb(
		const struct imx_ipu_core_data *data,
		struct mx3fb_platform_data *pdata)
{
	struct resource res[] = {
		{
			.start = data->iobase + 0xb4,
			.end = data->iobase + 0x1bf,
			.flags = IORESOURCE_MEM,
		},
	};

	if (IS_ERR_OR_NULL(imx_ipu_coredev))
		return ERR_PTR(-ENODEV);

	pdata->dma_dev = &imx_ipu_coredev->dev;

	return imx_add_platform_device_dmamask("mx3_sdc_fb", -1,
			res, ARRAY_SIZE(res), pdata, sizeof(*pdata),
			DMA_BIT_MASK(32));
}