1 /* 2 * MIPI DSI Bus 3 * 4 * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. 5 * Andrzej Hajda <a.hajda@samsung.com> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25 * USE OR OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #include <drm/drm_mipi_dsi.h> 29 30 #include <linux/device.h> 31 #include <linux/module.h> 32 #include <linux/of_device.h> 33 #include <linux/pm_runtime.h> 34 #include <linux/slab.h> 35 36 #include <video/mipi_display.h> 37 38 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv) 39 { 40 return of_driver_match_device(dev, drv); 41 } 42 43 static const struct dev_pm_ops mipi_dsi_device_pm_ops = { 44 .runtime_suspend = pm_generic_runtime_suspend, 45 .runtime_resume = pm_generic_runtime_resume, 46 .suspend = pm_generic_suspend, 47 .resume = pm_generic_resume, 48 .freeze = pm_generic_freeze, 49 .thaw = pm_generic_thaw, 50 .poweroff = pm_generic_poweroff, 51 .restore = pm_generic_restore, 52 }; 53 54 static struct bus_type mipi_dsi_bus_type = { 55 .name = "mipi-dsi", 56 .match = mipi_dsi_device_match, 57 .pm = &mipi_dsi_device_pm_ops, 58 }; 59 60 static void mipi_dsi_dev_release(struct device *dev) 61 { 62 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 63 64 of_node_put(dev->of_node); 65 kfree(dsi); 66 } 67 68 static const struct device_type mipi_dsi_device_type = { 69 .release = mipi_dsi_dev_release, 70 }; 71 72 static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host) 73 { 74 struct mipi_dsi_device *dsi; 75 76 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); 77 if (!dsi) 78 return ERR_PTR(-ENOMEM); 79 80 dsi->host = host; 81 dsi->dev.bus = &mipi_dsi_bus_type; 82 dsi->dev.parent = host->dev; 83 dsi->dev.type = &mipi_dsi_device_type; 84 85 device_initialize(&dsi->dev); 86 87 return dsi; 88 } 89 90 static int mipi_dsi_device_add(struct mipi_dsi_device *dsi) 91 { 92 struct mipi_dsi_host *host = dsi->host; 93 94 dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel); 95 96 return device_add(&dsi->dev); 97 } 98 99 static struct mipi_dsi_device * 100 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) 101 { 102 struct mipi_dsi_device *dsi; 103 struct device *dev = host->dev; 104 int ret; 105 u32 reg; 106 107 ret = of_property_read_u32(node, "reg", ®); 108 if (ret) { 109 dev_err(dev, "device node %s has no valid reg property: %d\n", 110 node->full_name, ret); 111 return ERR_PTR(-EINVAL); 112 } 113 114 if (reg > 3) { 115 dev_err(dev, "device node %s has invalid reg property: %u\n", 116 node->full_name, reg); 117 return ERR_PTR(-EINVAL); 118 } 119 120 dsi = mipi_dsi_device_alloc(host); 121 if (IS_ERR(dsi)) { 122 dev_err(dev, "failed to allocate DSI device %s: %ld\n", 123 node->full_name, PTR_ERR(dsi)); 124 return dsi; 125 } 126 127 dsi->dev.of_node = of_node_get(node); 128 dsi->channel = reg; 129 130 ret = mipi_dsi_device_add(dsi); 131 if (ret) { 132 dev_err(dev, "failed to add DSI device %s: %d\n", 133 node->full_name, ret); 134 kfree(dsi); 135 return ERR_PTR(ret); 136 } 137 138 return dsi; 139 } 140 141 int mipi_dsi_host_register(struct mipi_dsi_host *host) 142 { 143 struct device_node *node; 144 145 for_each_available_child_of_node(host->dev->of_node, node) 146 of_mipi_dsi_device_add(host, node); 147 148 return 0; 149 } 150 EXPORT_SYMBOL(mipi_dsi_host_register); 151 152 static int mipi_dsi_remove_device_fn(struct device *dev, void *priv) 153 { 154 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 155 156 device_unregister(&dsi->dev); 157 158 return 0; 159 } 160 161 void mipi_dsi_host_unregister(struct mipi_dsi_host *host) 162 { 163 device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn); 164 } 165 EXPORT_SYMBOL(mipi_dsi_host_unregister); 166 167 /** 168 * mipi_dsi_attach - attach a DSI device to its DSI host 169 * @dsi: DSI peripheral 170 */ 171 int mipi_dsi_attach(struct mipi_dsi_device *dsi) 172 { 173 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 174 175 if (!ops || !ops->attach) 176 return -ENOSYS; 177 178 return ops->attach(dsi->host, dsi); 179 } 180 EXPORT_SYMBOL(mipi_dsi_attach); 181 182 /** 183 * mipi_dsi_detach - detach a DSI device from its DSI host 184 * @dsi: DSI peripheral 185 */ 186 int mipi_dsi_detach(struct mipi_dsi_device *dsi) 187 { 188 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 189 190 if (!ops || !ops->detach) 191 return -ENOSYS; 192 193 return ops->detach(dsi->host, dsi); 194 } 195 EXPORT_SYMBOL(mipi_dsi_detach); 196 197 /** 198 * mipi_dsi_dcs_write - send DCS write command 199 * @dsi: DSI device 200 * @channel: virtual channel 201 * @data: pointer to the command followed by parameters 202 * @len: length of @data 203 */ 204 int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel, 205 const void *data, size_t len) 206 { 207 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 208 struct mipi_dsi_msg msg = { 209 .channel = channel, 210 .tx_buf = data, 211 .tx_len = len 212 }; 213 214 if (!ops || !ops->transfer) 215 return -ENOSYS; 216 217 switch (len) { 218 case 0: 219 return -EINVAL; 220 case 1: 221 msg.type = MIPI_DSI_DCS_SHORT_WRITE; 222 break; 223 case 2: 224 msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; 225 break; 226 default: 227 msg.type = MIPI_DSI_DCS_LONG_WRITE; 228 break; 229 } 230 231 return ops->transfer(dsi->host, &msg); 232 } 233 EXPORT_SYMBOL(mipi_dsi_dcs_write); 234 235 /** 236 * mipi_dsi_dcs_read - send DCS read request command 237 * @dsi: DSI device 238 * @channel: virtual channel 239 * @cmd: DCS read command 240 * @data: pointer to read buffer 241 * @len: length of @data 242 * 243 * Function returns number of read bytes or error code. 244 */ 245 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel, 246 u8 cmd, void *data, size_t len) 247 { 248 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 249 struct mipi_dsi_msg msg = { 250 .channel = channel, 251 .type = MIPI_DSI_DCS_READ, 252 .tx_buf = &cmd, 253 .tx_len = 1, 254 .rx_buf = data, 255 .rx_len = len 256 }; 257 258 if (!ops || !ops->transfer) 259 return -ENOSYS; 260 261 return ops->transfer(dsi->host, &msg); 262 } 263 EXPORT_SYMBOL(mipi_dsi_dcs_read); 264 265 static int mipi_dsi_drv_probe(struct device *dev) 266 { 267 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); 268 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 269 270 return drv->probe(dsi); 271 } 272 273 static int mipi_dsi_drv_remove(struct device *dev) 274 { 275 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); 276 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 277 278 return drv->remove(dsi); 279 } 280 281 /** 282 * mipi_dsi_driver_register - register a driver for DSI devices 283 * @drv: DSI driver structure 284 */ 285 int mipi_dsi_driver_register(struct mipi_dsi_driver *drv) 286 { 287 drv->driver.bus = &mipi_dsi_bus_type; 288 if (drv->probe) 289 drv->driver.probe = mipi_dsi_drv_probe; 290 if (drv->remove) 291 drv->driver.remove = mipi_dsi_drv_remove; 292 293 return driver_register(&drv->driver); 294 } 295 EXPORT_SYMBOL(mipi_dsi_driver_register); 296 297 /** 298 * mipi_dsi_driver_unregister - unregister a driver for DSI devices 299 * @drv: DSI driver structure 300 */ 301 void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv) 302 { 303 driver_unregister(&drv->driver); 304 } 305 EXPORT_SYMBOL(mipi_dsi_driver_unregister); 306 307 static int __init mipi_dsi_bus_init(void) 308 { 309 return bus_register(&mipi_dsi_bus_type); 310 } 311 postcore_initcall(mipi_dsi_bus_init); 312 313 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>"); 314 MODULE_DESCRIPTION("MIPI DSI Bus"); 315 MODULE_LICENSE("GPL and additional rights"); 316