summaryrefslogtreecommitdiff
path: root/drivers/gpu/imx/dpu/dpu-store.c
blob: cbd06b83581bcd59f2a9734a81a4a0944e40d544 (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
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright 2018-2019 NXP
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * 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/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include "dpu-prv.h"

#define PIXENGCFG_STATIC		0x8
#define DIV(n)				(((n) & 0xFF) << 16)
#define DIV_RESET			0x80

struct dpu_store {
	void __iomem *pec_base;
	void __iomem *base;
	struct mutex mutex;
	int id;
	bool inuse;
	struct dpu_soc *dpu;
};

static inline u32 dpu_pec_st_read(struct dpu_store *st, unsigned int offset)
{
	return readl(st->pec_base + offset);
}

static inline void dpu_pec_st_write(struct dpu_store *st,
				    unsigned int offset, u32 value)
{
	writel(value, st->pec_base + offset);
}

void store_pixengcfg_syncmode_fixup(struct dpu_store *st, bool enable)
{
	struct dpu_soc *dpu;
	u32 val;

	if (!st)
		return;

	dpu = st->dpu;

	mutex_lock(&st->mutex);
	val = dpu_pec_st_read(st, PIXENGCFG_STATIC);
	if (enable)
		val |= BIT(16);
	else
		val &= ~BIT(16);
	dpu_pec_st_write(st, PIXENGCFG_STATIC, val);
	mutex_unlock(&st->mutex);
}
EXPORT_SYMBOL_GPL(store_pixengcfg_syncmode_fixup);

struct dpu_store *dpu_st_get(struct dpu_soc *dpu, int id)
{
	struct dpu_store *st;
	int i;

	for (i = 0; i < ARRAY_SIZE(st_ids); i++)
		if (st_ids[i] == id)
			break;

	if (i == ARRAY_SIZE(st_ids))
		return ERR_PTR(-EINVAL);

	st = dpu->st_priv[i];

	mutex_lock(&st->mutex);

	if (st->inuse) {
		mutex_unlock(&st->mutex);
		return ERR_PTR(-EBUSY);
	}

	st->inuse = true;

	mutex_unlock(&st->mutex);

	return st;
}
EXPORT_SYMBOL_GPL(dpu_st_get);

void dpu_st_put(struct dpu_store *st)
{
	mutex_lock(&st->mutex);

	st->inuse = false;

	mutex_unlock(&st->mutex);
}
EXPORT_SYMBOL_GPL(dpu_st_put);

void _dpu_st_init(struct dpu_soc *dpu, unsigned int id)
{
	struct dpu_store *st;
	int i;

	for (i = 0; i < ARRAY_SIZE(st_ids); i++)
		if (st_ids[i] == id)
			break;

	if (WARN_ON(i == ARRAY_SIZE(st_ids)))
		return;

	st = dpu->st_priv[i];

	dpu_pec_st_write(st, PIXENGCFG_STATIC, SHDEN | DIV(DIV_RESET));
}

int dpu_st_init(struct dpu_soc *dpu, unsigned int id,
		unsigned long pec_base, unsigned long base)
{
	struct dpu_store *st;
	int i;

	st = devm_kzalloc(dpu->dev, sizeof(*st), GFP_KERNEL);
	if (!st)
		return -ENOMEM;

	for (i = 0; i < ARRAY_SIZE(st_ids); i++)
		if (st_ids[i] == id)
			break;

	if (i == ARRAY_SIZE(st_ids))
		return -EINVAL;

	dpu->st_priv[i] = st;

	st->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_32);
	if (!st->pec_base)
		return -ENOMEM;

	st->base = devm_ioremap(dpu->dev, base, SZ_256);
	if (!st->base)
		return -ENOMEM;

	st->dpu = dpu;
	st->id = id;
	mutex_init(&st->mutex);

	_dpu_st_init(dpu, id);

	return 0;
}