aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c
blob: 1a4e14525bc30253e6de3c679e6de2259ee9c554 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/slab.h>
#include <linux/mod_devicetable.h>
#include <linux/of_device.h>

#include "cam_isp_hw.h"
#include "cam_hw_intf.h"
#include "cam_csid_ppi_core.h"
#include "cam_csid_ppi_dev.h"
#include "cam_debug_util.h"

static struct cam_hw_intf *cam_csid_ppi_hw_list[CAM_CSID_PPI_HW_MAX] = {
	0, 0, 0, 0};
static char ppi_dev_name[8];

int cam_csid_ppi_probe(struct platform_device *pdev)
{
	struct cam_hw_intf            *ppi_hw_intf;
	struct cam_hw_info            *ppi_hw_info;
	struct cam_csid_ppi_hw        *ppi_dev = NULL;
	const struct of_device_id     *match_dev = NULL;
	struct cam_csid_ppi_hw_info   *ppi_hw_data = NULL;
	uint32_t                       ppi_dev_idx;
	int                            rc = 0;

	CAM_DBG(CAM_ISP, "PPI probe called");

	ppi_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
	if (!ppi_hw_intf) {
		rc = -ENOMEM;
		goto err;
	}

	ppi_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
	if (!ppi_hw_info) {
		rc = -ENOMEM;
		goto free_hw_intf;
	}

	ppi_dev = kzalloc(sizeof(struct cam_csid_ppi_hw), GFP_KERNEL);
	if (!ppi_dev) {
		rc = -ENOMEM;
		goto free_hw_info;
	}

	/* get csid ppi hw index */
	of_property_read_u32(pdev->dev.of_node, "cell-index", &ppi_dev_idx);

	/* get csid ppi hw information */
	match_dev = of_match_device(pdev->dev.driver->of_match_table,
		&pdev->dev);
	if (!match_dev) {
		CAM_ERR(CAM_ISP, "No matching table for the CSID PPI HW!");
		rc = -EINVAL;
		goto free_dev;
	}

	memset(ppi_dev_name, 0, sizeof(ppi_dev_name));
	snprintf(ppi_dev_name, sizeof(ppi_dev_name), "ppi%1u", ppi_dev_idx);

	ppi_hw_intf->hw_idx  = ppi_dev_idx;
	ppi_hw_intf->hw_priv = ppi_hw_info;

	ppi_hw_info->core_info         = ppi_dev;
	ppi_hw_info->soc_info.pdev     = pdev;
	ppi_hw_info->soc_info.dev      = &pdev->dev;
	ppi_hw_info->soc_info.dev_name = ppi_dev_name;
	ppi_hw_info->soc_info.index    = ppi_dev_idx;

	ppi_hw_data = (struct cam_csid_ppi_hw_info  *)match_dev->data;
	/* need to setup the pdev before call the csid ppi hw probe init */
	ppi_dev->ppi_info = ppi_hw_data;

	rc = cam_csid_ppi_hw_probe_init(ppi_hw_intf, ppi_dev_idx);
	if (rc) {
		CAM_ERR(CAM_ISP, "PPI: Probe init failed!");
		goto free_dev;
	}

	platform_set_drvdata(pdev, ppi_dev);
	CAM_DBG(CAM_ISP, "PPI:%d probe successful",
		ppi_hw_intf->hw_idx);

	if (ppi_hw_intf->hw_idx < CAM_CSID_PPI_HW_MAX)
		cam_csid_ppi_hw_list[ppi_hw_intf->hw_idx] = ppi_hw_intf;
	else
		goto free_dev;

	return 0;
free_dev:
	kfree(ppi_dev);
free_hw_info:
	kfree(ppi_hw_info);
free_hw_intf:
	kfree(ppi_hw_intf);
err:
	return rc;
}

int cam_csid_ppi_remove(struct platform_device *pdev)
{
	struct cam_csid_ppi_hw         *ppi_dev = NULL;
	struct cam_hw_intf             *ppi_hw_intf;
	struct cam_hw_info             *ppi_hw_info;

	ppi_dev = (struct cam_csid_ppi_hw *)platform_get_drvdata(pdev);
	ppi_hw_intf = ppi_dev->hw_intf;
	ppi_hw_info = ppi_dev->hw_info;

	CAM_DBG(CAM_ISP, "PPI:%d remove", ppi_dev->hw_intf->hw_idx);

	cam_csid_ppi_hw_deinit(ppi_dev);

	/* release the ppi device memory */
	kfree(ppi_dev);
	kfree(ppi_hw_info);
	kfree(ppi_hw_intf);
	return 0;
}

int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw,
	uint32_t hw_idx)
{
	int rc = 0;

	if (cam_csid_ppi_hw_list[hw_idx]) {
		*csid_ppi_hw = cam_csid_ppi_hw_list[hw_idx];
	} else {
		*csid_ppi_hw = NULL;
		rc = -1;
	}

	return rc;
}
EXPORT_SYMBOL(cam_csid_ppi_hw_init);