Skip to content

Commit 5e2368a

Browse files
committed
Merge tag 'drm/panel/for-4.6-rc1' of http://anongit.freedesktop.org/git/tegra/linux into drm-next
drm/panel: Changes for v4.6-rc1 This contains a refactoring of parts of the DSI core to allow creating DSI devices from non-DSI control busses (i.e. I2C, SPI, ...). Other than that there's support for a couple of new panels as well as a few cleanup patches. * tag 'drm/panel/for-4.6-rc1' of http://anongit.freedesktop.org/git/tegra/linux: drm/bridge: Make (pre/post) enable/disable callbacks optional drm/panel: simple: Add URT UMSH-8596MD-xT panels support dt-bindings: Add URT UMSH-8596MD-xT panel bindings of: Add United Radiant Technology Corporation vendor prefix drm/panel: simple: Support for LG lp120up1 panel dt-bindings: Add LG lp120up1 panel bindings drm/panel: simple: Fix g121x1_l03 hsync/vsync polarity drm/dsi: Get DSI host by DT device node drm/dsi: Add routine to unregister a DSI device drm/dsi: Try to match non-DT DSI devices drm/dsi: Use mipi_dsi_device_register_full() for DSI device creation drm/dsi: Check for CONFIG_OF when defining of_mipi_dsi_device_add()
2 parents 0e5dc9a + c8a3b2a commit 5e2368a

File tree

8 files changed

+262
-16
lines changed

8 files changed

+262
-16
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
LG 12.0" (1920x1280 pixels) TFT LCD panel
2+
3+
Required properties:
4+
- compatible: should be "lg,lp120up1"
5+
6+
This binding is compatible with the simple-panel binding, which is specified
7+
in simple-panel.txt in this directory.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
United Radiant Technology UMSH-8596MD-xT 7.0" WVGA TFT LCD panel
2+
3+
Supported are LVDS versions (-11T, -19T) and parallel ones
4+
(-T, -1T, -7T, -20T).
5+
6+
Required properties:
7+
- compatible: should be one of:
8+
"urt,umsh-8596md-t",
9+
"urt,umsh-8596md-1t",
10+
"urt,umsh-8596md-7t",
11+
"urt,umsh-8596md-11t",
12+
"urt,umsh-8596md-19t",
13+
"urt,umsh-8596md-20t".
14+
15+
This binding is compatible with the simple-panel binding, which is specified
16+
in simple-panel.txt in this directory.

Documentation/devicetree/bindings/vendor-prefixes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ tplink TP-LINK Technologies Co., Ltd.
240240
tronfy Tronfy
241241
truly Truly Semiconductors Limited
242242
upisemi uPI Semiconductor Corp.
243+
urt United Radiant Technology Corporation
243244
usi Universal Scientific Industrial Co., Ltd.
244245
v3 V3 Semiconductor
245246
variscite Variscite Ltd.

drivers/gpu/drm/drm_bridge.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ void drm_bridge_disable(struct drm_bridge *bridge)
186186

187187
drm_bridge_disable(bridge->next);
188188

189-
bridge->funcs->disable(bridge);
189+
if (bridge->funcs->disable)
190+
bridge->funcs->disable(bridge);
190191
}
191192
EXPORT_SYMBOL(drm_bridge_disable);
192193

@@ -206,7 +207,8 @@ void drm_bridge_post_disable(struct drm_bridge *bridge)
206207
if (!bridge)
207208
return;
208209

209-
bridge->funcs->post_disable(bridge);
210+
if (bridge->funcs->post_disable)
211+
bridge->funcs->post_disable(bridge);
210212

211213
drm_bridge_post_disable(bridge->next);
212214
}
@@ -256,7 +258,8 @@ void drm_bridge_pre_enable(struct drm_bridge *bridge)
256258

257259
drm_bridge_pre_enable(bridge->next);
258260

259-
bridge->funcs->pre_enable(bridge);
261+
if (bridge->funcs->pre_enable)
262+
bridge->funcs->pre_enable(bridge);
260263
}
261264
EXPORT_SYMBOL(drm_bridge_pre_enable);
262265

@@ -276,7 +279,8 @@ void drm_bridge_enable(struct drm_bridge *bridge)
276279
if (!bridge)
277280
return;
278281

279-
bridge->funcs->enable(bridge);
282+
if (bridge->funcs->enable)
283+
bridge->funcs->enable(bridge);
280284

281285
drm_bridge_enable(bridge->next);
282286
}

drivers/gpu/drm/drm_mipi_dsi.c

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@
4747

4848
static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
4949
{
50-
return of_driver_match_device(dev, drv);
50+
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
51+
52+
/* attempt OF style match */
53+
if (of_driver_match_device(dev, drv))
54+
return 1;
55+
56+
/* compare DSI device and driver names */
57+
if (!strcmp(dsi->name, drv->name))
58+
return 1;
59+
60+
return 0;
5161
}
5262

5363
static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -129,47 +139,132 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
129139
return device_add(&dsi->dev);
130140
}
131141

142+
#if IS_ENABLED(CONFIG_OF)
132143
static struct mipi_dsi_device *
133144
of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
134145
{
135-
struct mipi_dsi_device *dsi;
136146
struct device *dev = host->dev;
147+
struct mipi_dsi_device_info info = { };
137148
int ret;
138149
u32 reg;
139150

151+
if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
152+
dev_err(dev, "modalias failure on %s\n", node->full_name);
153+
return ERR_PTR(-EINVAL);
154+
}
155+
140156
ret = of_property_read_u32(node, "reg", &reg);
141157
if (ret) {
142158
dev_err(dev, "device node %s has no valid reg property: %d\n",
143159
node->full_name, ret);
144160
return ERR_PTR(-EINVAL);
145161
}
146162

147-
if (reg > 3) {
148-
dev_err(dev, "device node %s has invalid reg property: %u\n",
149-
node->full_name, reg);
163+
info.channel = reg;
164+
info.node = of_node_get(node);
165+
166+
return mipi_dsi_device_register_full(host, &info);
167+
}
168+
#else
169+
static struct mipi_dsi_device *
170+
of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
171+
{
172+
return ERR_PTR(-ENODEV);
173+
}
174+
#endif
175+
176+
/**
177+
* mipi_dsi_device_register_full - create a MIPI DSI device
178+
* @host: DSI host to which this device is connected
179+
* @info: pointer to template containing DSI device information
180+
*
181+
* Create a MIPI DSI device by using the device information provided by
182+
* mipi_dsi_device_info template
183+
*
184+
* Returns:
185+
* A pointer to the newly created MIPI DSI device, or, a pointer encoded
186+
* with an error
187+
*/
188+
struct mipi_dsi_device *
189+
mipi_dsi_device_register_full(struct mipi_dsi_host *host,
190+
const struct mipi_dsi_device_info *info)
191+
{
192+
struct mipi_dsi_device *dsi;
193+
struct device *dev = host->dev;
194+
int ret;
195+
196+
if (!info) {
197+
dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
198+
return ERR_PTR(-EINVAL);
199+
}
200+
201+
if (info->channel > 3) {
202+
dev_err(dev, "invalid virtual channel: %u\n", info->channel);
150203
return ERR_PTR(-EINVAL);
151204
}
152205

153206
dsi = mipi_dsi_device_alloc(host);
154207
if (IS_ERR(dsi)) {
155-
dev_err(dev, "failed to allocate DSI device %s: %ld\n",
156-
node->full_name, PTR_ERR(dsi));
208+
dev_err(dev, "failed to allocate DSI device %ld\n",
209+
PTR_ERR(dsi));
157210
return dsi;
158211
}
159212

160-
dsi->dev.of_node = of_node_get(node);
161-
dsi->channel = reg;
213+
dsi->dev.of_node = info->node;
214+
dsi->channel = info->channel;
215+
strlcpy(dsi->name, info->type, sizeof(dsi->name));
162216

163217
ret = mipi_dsi_device_add(dsi);
164218
if (ret) {
165-
dev_err(dev, "failed to add DSI device %s: %d\n",
166-
node->full_name, ret);
219+
dev_err(dev, "failed to add DSI device %d\n", ret);
167220
kfree(dsi);
168221
return ERR_PTR(ret);
169222
}
170223

171224
return dsi;
172225
}
226+
EXPORT_SYMBOL(mipi_dsi_device_register_full);
227+
228+
/**
229+
* mipi_dsi_device_unregister - unregister MIPI DSI device
230+
* @dsi: DSI peripheral device
231+
*/
232+
void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
233+
{
234+
device_unregister(&dsi->dev);
235+
}
236+
EXPORT_SYMBOL(mipi_dsi_device_unregister);
237+
238+
static DEFINE_MUTEX(host_lock);
239+
static LIST_HEAD(host_list);
240+
241+
/**
242+
* of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
243+
* device tree node
244+
* @node: device tree node
245+
*
246+
* Returns:
247+
* A pointer to the MIPI DSI host corresponding to @node or NULL if no
248+
* such device exists (or has not been registered yet).
249+
*/
250+
struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
251+
{
252+
struct mipi_dsi_host *host;
253+
254+
mutex_lock(&host_lock);
255+
256+
list_for_each_entry(host, &host_list, list) {
257+
if (host->dev->of_node == node) {
258+
mutex_unlock(&host_lock);
259+
return host;
260+
}
261+
}
262+
263+
mutex_unlock(&host_lock);
264+
265+
return NULL;
266+
}
267+
EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
173268

174269
int mipi_dsi_host_register(struct mipi_dsi_host *host)
175270
{
@@ -182,6 +277,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
182277
of_mipi_dsi_device_add(host, node);
183278
}
184279

280+
mutex_lock(&host_lock);
281+
list_add_tail(&host->list, &host_list);
282+
mutex_unlock(&host_lock);
283+
185284
return 0;
186285
}
187286
EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -190,14 +289,18 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
190289
{
191290
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
192291

193-
device_unregister(&dsi->dev);
292+
mipi_dsi_device_unregister(dsi);
194293

195294
return 0;
196295
}
197296

198297
void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
199298
{
200299
device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
300+
301+
mutex_lock(&host_lock);
302+
list_del_init(&host->list);
303+
mutex_unlock(&host_lock);
201304
}
202305
EXPORT_SYMBOL(mipi_dsi_host_unregister);
203306

drivers/gpu/drm/panel/panel-simple.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ static const struct drm_display_mode innolux_g121x1_l03_mode = {
847847
.vsync_end = 768 + 38 + 1,
848848
.vtotal = 768 + 38 + 1 + 0,
849849
.vrefresh = 60,
850+
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
850851
};
851852

852853
static const struct panel_desc innolux_g121x1_l03 = {
@@ -982,6 +983,29 @@ static const struct panel_desc lg_lb070wv8 = {
982983
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
983984
};
984985

986+
static const struct drm_display_mode lg_lp120up1_mode = {
987+
.clock = 162300,
988+
.hdisplay = 1920,
989+
.hsync_start = 1920 + 40,
990+
.hsync_end = 1920 + 40 + 40,
991+
.htotal = 1920 + 40 + 40+ 80,
992+
.vdisplay = 1280,
993+
.vsync_start = 1280 + 4,
994+
.vsync_end = 1280 + 4 + 4,
995+
.vtotal = 1280 + 4 + 4 + 12,
996+
.vrefresh = 60,
997+
};
998+
999+
static const struct panel_desc lg_lp120up1 = {
1000+
.modes = &lg_lp120up1_mode,
1001+
.num_modes = 1,
1002+
.bpc = 8,
1003+
.size = {
1004+
.width = 267,
1005+
.height = 183,
1006+
},
1007+
};
1008+
9851009
static const struct drm_display_mode lg_lp129qe_mode = {
9861010
.clock = 285250,
9871011
.hdisplay = 2560,
@@ -1177,6 +1201,42 @@ static const struct panel_desc shelly_sca07010_bfn_lnn = {
11771201
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
11781202
};
11791203

1204+
static const struct display_timing urt_umsh_8596md_timing = {
1205+
.pixelclock = { 33260000, 33260000, 33260000 },
1206+
.hactive = { 800, 800, 800 },
1207+
.hfront_porch = { 41, 41, 41 },
1208+
.hback_porch = { 216 - 128, 216 - 128, 216 - 128 },
1209+
.hsync_len = { 71, 128, 128 },
1210+
.vactive = { 480, 480, 480 },
1211+
.vfront_porch = { 10, 10, 10 },
1212+
.vback_porch = { 35 - 2, 35 - 2, 35 - 2 },
1213+
.vsync_len = { 2, 2, 2 },
1214+
.flags = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE |
1215+
DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
1216+
};
1217+
1218+
static const struct panel_desc urt_umsh_8596md_lvds = {
1219+
.timings = &urt_umsh_8596md_timing,
1220+
.num_timings = 1,
1221+
.bpc = 6,
1222+
.size = {
1223+
.width = 152,
1224+
.height = 91,
1225+
},
1226+
.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
1227+
};
1228+
1229+
static const struct panel_desc urt_umsh_8596md_parallel = {
1230+
.timings = &urt_umsh_8596md_timing,
1231+
.num_timings = 1,
1232+
.bpc = 6,
1233+
.size = {
1234+
.width = 152,
1235+
.height = 91,
1236+
},
1237+
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
1238+
};
1239+
11801240
static const struct of_device_id platform_of_match[] = {
11811241
{
11821242
.compatible = "ampire,am800480r3tmqwa1h",
@@ -1256,6 +1316,9 @@ static const struct of_device_id platform_of_match[] = {
12561316
}, {
12571317
.compatible = "lg,lb070wv8",
12581318
.data = &lg_lb070wv8,
1319+
}, {
1320+
.compatible = "lg,lp120up1",
1321+
.data = &lg_lp120up1,
12591322
}, {
12601323
.compatible = "lg,lp129qe",
12611324
.data = &lg_lp129qe,
@@ -1280,6 +1343,24 @@ static const struct of_device_id platform_of_match[] = {
12801343
}, {
12811344
.compatible = "shelly,sca07010-bfn-lnn",
12821345
.data = &shelly_sca07010_bfn_lnn,
1346+
}, {
1347+
.compatible = "urt,umsh-8596md-t",
1348+
.data = &urt_umsh_8596md_parallel,
1349+
}, {
1350+
.compatible = "urt,umsh-8596md-1t",
1351+
.data = &urt_umsh_8596md_parallel,
1352+
}, {
1353+
.compatible = "urt,umsh-8596md-7t",
1354+
.data = &urt_umsh_8596md_parallel,
1355+
}, {
1356+
.compatible = "urt,umsh-8596md-11t",
1357+
.data = &urt_umsh_8596md_lvds,
1358+
}, {
1359+
.compatible = "urt,umsh-8596md-19t",
1360+
.data = &urt_umsh_8596md_lvds,
1361+
}, {
1362+
.compatible = "urt,umsh-8596md-20t",
1363+
.data = &urt_umsh_8596md_parallel,
12831364
}, {
12841365
/* sentinel */
12851366
}

0 commit comments

Comments
 (0)