adf_client.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. /*
  2. * Copyright (C) 2013 Google, Inc.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/kthread.h>
  15. #include <linux/mutex.h>
  16. #include <linux/slab.h>
  17. #include "sw_sync.h"
  18. #include <video/adf.h>
  19. #include <video/adf_client.h>
  20. #include <video/adf_format.h>
  21. #include "adf.h"
  22. static inline bool vsync_active(u8 state)
  23. {
  24. return state == DRM_MODE_DPMS_ON || state == DRM_MODE_DPMS_STANDBY;
  25. }
  26. /**
  27. * adf_interface_blank - set interface's DPMS state
  28. *
  29. * @intf: the interface
  30. * @state: one of %DRM_MODE_DPMS_*
  31. *
  32. * Returns 0 on success or -errno on failure.
  33. */
  34. int adf_interface_blank(struct adf_interface *intf, u8 state)
  35. {
  36. struct adf_device *dev = adf_interface_parent(intf);
  37. u8 prev_state;
  38. bool disable_vsync;
  39. bool enable_vsync;
  40. int ret = 0;
  41. struct adf_event_refcount *vsync_refcount;
  42. if (!intf->ops || !intf->ops->blank)
  43. return -EOPNOTSUPP;
  44. if (state > DRM_MODE_DPMS_OFF)
  45. return -EINVAL;
  46. mutex_lock(&dev->client_lock);
  47. if (state != DRM_MODE_DPMS_ON)
  48. flush_kthread_worker(&dev->post_worker);
  49. mutex_lock(&intf->base.event_lock);
  50. vsync_refcount = adf_obj_find_event_refcount(&intf->base,
  51. ADF_EVENT_VSYNC);
  52. if (!vsync_refcount) {
  53. ret = -ENOMEM;
  54. goto done;
  55. }
  56. prev_state = intf->dpms_state;
  57. if (prev_state == state) {
  58. ret = -EBUSY;
  59. goto done;
  60. }
  61. disable_vsync = vsync_active(prev_state) &&
  62. !vsync_active(state) &&
  63. vsync_refcount->refcount;
  64. enable_vsync = !vsync_active(prev_state) &&
  65. vsync_active(state) &&
  66. vsync_refcount->refcount;
  67. if (disable_vsync)
  68. intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
  69. false);
  70. ret = intf->ops->blank(intf, state);
  71. if (ret < 0) {
  72. if (disable_vsync)
  73. intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
  74. true);
  75. goto done;
  76. }
  77. if (enable_vsync)
  78. intf->base.ops->set_event(&intf->base, ADF_EVENT_VSYNC,
  79. true);
  80. intf->dpms_state = state;
  81. done:
  82. mutex_unlock(&intf->base.event_lock);
  83. mutex_unlock(&dev->client_lock);
  84. return ret;
  85. }
  86. EXPORT_SYMBOL(adf_interface_blank);
  87. /**
  88. * adf_interface_blank - get interface's current DPMS state
  89. *
  90. * @intf: the interface
  91. *
  92. * Returns one of %DRM_MODE_DPMS_*.
  93. */
  94. u8 adf_interface_dpms_state(struct adf_interface *intf)
  95. {
  96. struct adf_device *dev = adf_interface_parent(intf);
  97. u8 dpms_state;
  98. mutex_lock(&dev->client_lock);
  99. dpms_state = intf->dpms_state;
  100. mutex_unlock(&dev->client_lock);
  101. return dpms_state;
  102. }
  103. EXPORT_SYMBOL(adf_interface_dpms_state);
  104. /**
  105. * adf_interface_current_mode - get interface's current display mode
  106. *
  107. * @intf: the interface
  108. * @mode: returns the current mode
  109. */
  110. void adf_interface_current_mode(struct adf_interface *intf,
  111. struct drm_mode_modeinfo *mode)
  112. {
  113. struct adf_device *dev = adf_interface_parent(intf);
  114. mutex_lock(&dev->client_lock);
  115. memcpy(mode, &intf->current_mode, sizeof(*mode));
  116. mutex_unlock(&dev->client_lock);
  117. }
  118. EXPORT_SYMBOL(adf_interface_current_mode);
  119. /**
  120. * adf_interface_modelist - get interface's modelist
  121. *
  122. * @intf: the interface
  123. * @modelist: storage for the modelist (optional)
  124. * @n_modes: length of @modelist
  125. *
  126. * If @modelist is not NULL, adf_interface_modelist() will copy up to @n_modes
  127. * modelist entries into @modelist.
  128. *
  129. * Returns the length of the modelist.
  130. */
  131. size_t adf_interface_modelist(struct adf_interface *intf,
  132. struct drm_mode_modeinfo *modelist, size_t n_modes)
  133. {
  134. unsigned long flags;
  135. size_t retval;
  136. read_lock_irqsave(&intf->hotplug_modelist_lock, flags);
  137. if (modelist)
  138. memcpy(modelist, intf->modelist, sizeof(modelist[0]) *
  139. min(n_modes, intf->n_modes));
  140. retval = intf->n_modes;
  141. read_unlock_irqrestore(&intf->hotplug_modelist_lock, flags);
  142. return retval;
  143. }
  144. EXPORT_SYMBOL(adf_interface_modelist);
  145. /**
  146. * adf_interface_set_mode - set interface's display mode
  147. *
  148. * @intf: the interface
  149. * @mode: the new mode
  150. *
  151. * Returns 0 on success or -errno on failure.
  152. */
  153. int adf_interface_set_mode(struct adf_interface *intf,
  154. struct drm_mode_modeinfo *mode)
  155. {
  156. struct adf_device *dev = adf_interface_parent(intf);
  157. int ret = 0;
  158. if (!intf->ops || !intf->ops->modeset)
  159. return -EOPNOTSUPP;
  160. mutex_lock(&dev->client_lock);
  161. flush_kthread_worker(&dev->post_worker);
  162. ret = intf->ops->modeset(intf, mode);
  163. if (ret < 0)
  164. goto done;
  165. memcpy(&intf->current_mode, mode, sizeof(*mode));
  166. done:
  167. mutex_unlock(&dev->client_lock);
  168. return ret;
  169. }
  170. EXPORT_SYMBOL(adf_interface_set_mode);
  171. /**
  172. * adf_interface_screen_size - get size of screen connected to interface
  173. *
  174. * @intf: the interface
  175. * @width_mm: returns the screen width in mm
  176. * @height_mm: returns the screen width in mm
  177. *
  178. * Returns 0 on success or -errno on failure.
  179. */
  180. int adf_interface_get_screen_size(struct adf_interface *intf, u16 *width_mm,
  181. u16 *height_mm)
  182. {
  183. struct adf_device *dev = adf_interface_parent(intf);
  184. int ret;
  185. if (!intf->ops || !intf->ops->screen_size)
  186. return -EOPNOTSUPP;
  187. mutex_lock(&dev->client_lock);
  188. ret = intf->ops->screen_size(intf, width_mm, height_mm);
  189. mutex_unlock(&dev->client_lock);
  190. return ret;
  191. }
  192. EXPORT_SYMBOL(adf_interface_get_screen_size);
  193. /**
  194. * adf_overlay_engine_supports_format - returns whether a format is in an
  195. * overlay engine's supported list
  196. *
  197. * @eng: the overlay engine
  198. * @format: format fourcc
  199. */
  200. bool adf_overlay_engine_supports_format(struct adf_overlay_engine *eng,
  201. u32 format)
  202. {
  203. size_t i;
  204. for (i = 0; i < eng->ops->n_supported_formats; i++)
  205. if (format == eng->ops->supported_formats[i])
  206. return true;
  207. return false;
  208. }
  209. EXPORT_SYMBOL(adf_overlay_engine_supports_format);
  210. static int adf_buffer_validate(struct adf_buffer *buf)
  211. {
  212. struct adf_overlay_engine *eng = buf->overlay_engine;
  213. struct device *dev = &eng->base.dev;
  214. struct adf_device *parent = adf_overlay_engine_parent(eng);
  215. u8 hsub, vsub, num_planes, cpp[ADF_MAX_PLANES], i;
  216. if (!adf_overlay_engine_supports_format(eng, buf->format)) {
  217. char format_str[ADF_FORMAT_STR_SIZE];
  218. adf_format_str(buf->format, format_str);
  219. dev_err(dev, "unsupported format %s\n", format_str);
  220. return -EINVAL;
  221. }
  222. if (!adf_format_is_standard(buf->format))
  223. return parent->ops->validate_custom_format(parent, buf);
  224. hsub = adf_format_horz_chroma_subsampling(buf->format);
  225. vsub = adf_format_vert_chroma_subsampling(buf->format);
  226. num_planes = adf_format_num_planes(buf->format);
  227. for (i = 0; i < num_planes; i++)
  228. cpp[i] = adf_format_plane_cpp(buf->format, i);
  229. return adf_format_validate_yuv(parent, buf, num_planes, hsub, vsub,
  230. cpp);
  231. }
  232. static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf,
  233. struct adf_buffer_mapping *mapping)
  234. {
  235. int ret = 0;
  236. size_t i;
  237. for (i = 0; i < buf->n_planes; i++) {
  238. struct dma_buf_attachment *attachment;
  239. struct sg_table *sg_table;
  240. attachment = dma_buf_attach(buf->dma_bufs[i], dev->dev);
  241. if (IS_ERR(attachment)) {
  242. ret = PTR_ERR(attachment);
  243. dev_err(&dev->base.dev, "attaching plane %zu failed: %d\n",
  244. i, ret);
  245. goto done;
  246. }
  247. mapping->attachments[i] = attachment;
  248. sg_table = dma_buf_map_attachment(attachment, DMA_TO_DEVICE);
  249. if (IS_ERR(sg_table)) {
  250. ret = PTR_ERR(sg_table);
  251. dev_err(&dev->base.dev, "mapping plane %zu failed: %d",
  252. i, ret);
  253. goto done;
  254. } else if (!sg_table) {
  255. ret = -ENOMEM;
  256. dev_err(&dev->base.dev, "mapping plane %zu failed\n",
  257. i);
  258. goto done;
  259. }
  260. mapping->sg_tables[i] = sg_table;
  261. }
  262. done:
  263. if (ret < 0)
  264. adf_buffer_mapping_cleanup(mapping, buf);
  265. return ret;
  266. }
  267. static struct sync_fence *adf_sw_complete_fence(struct adf_device *dev)
  268. {
  269. struct sync_pt *pt;
  270. struct sync_fence *complete_fence;
  271. if (!dev->timeline) {
  272. dev->timeline = sw_sync_timeline_create(dev->base.name);
  273. if (!dev->timeline)
  274. return ERR_PTR(-ENOMEM);
  275. dev->timeline_max = 1;
  276. }
  277. dev->timeline_max++;
  278. pt = sw_sync_pt_create(dev->timeline, dev->timeline_max);
  279. if (!pt)
  280. goto err_pt_create;
  281. complete_fence = sync_fence_create(dev->base.name, pt);
  282. if (!complete_fence)
  283. goto err_fence_create;
  284. return complete_fence;
  285. err_fence_create:
  286. sync_pt_free(pt);
  287. err_pt_create:
  288. dev->timeline_max--;
  289. return ERR_PTR(-ENOSYS);
  290. }
  291. /**
  292. * adf_device_post - flip to a new set of buffers
  293. *
  294. * @dev: device targeted by the flip
  295. * @intfs: interfaces targeted by the flip
  296. * @n_intfs: number of targeted interfaces
  297. * @bufs: description of buffers displayed
  298. * @n_bufs: number of buffers displayed
  299. * @custom_data: driver-private data
  300. * @custom_data_size: size of driver-private data
  301. *
  302. * adf_device_post() will copy @intfs, @bufs, and @custom_data, so they may
  303. * point to variables on the stack. adf_device_post() also takes its own
  304. * reference on each of the dma-bufs in @bufs. The adf_device_post_nocopy()
  305. * variant transfers ownership of these resources to ADF instead.
  306. *
  307. * On success, returns a sync fence which signals when the buffers are removed
  308. * from the screen. On failure, returns ERR_PTR(-errno).
  309. */
  310. struct sync_fence *adf_device_post(struct adf_device *dev,
  311. struct adf_interface **intfs, size_t n_intfs,
  312. struct adf_buffer *bufs, size_t n_bufs, void *custom_data,
  313. size_t custom_data_size)
  314. {
  315. struct adf_interface **intfs_copy = NULL;
  316. struct adf_buffer *bufs_copy = NULL;
  317. void *custom_data_copy = NULL;
  318. struct sync_fence *ret;
  319. size_t i;
  320. intfs_copy = kzalloc(sizeof(intfs_copy[0]) * n_intfs, GFP_KERNEL);
  321. if (!intfs_copy)
  322. return ERR_PTR(-ENOMEM);
  323. bufs_copy = kzalloc(sizeof(bufs_copy[0]) * n_bufs, GFP_KERNEL);
  324. if (!bufs_copy) {
  325. ret = ERR_PTR(-ENOMEM);
  326. goto err_alloc;
  327. }
  328. custom_data_copy = kzalloc(custom_data_size, GFP_KERNEL);
  329. if (!custom_data_copy) {
  330. ret = ERR_PTR(-ENOMEM);
  331. goto err_alloc;
  332. }
  333. for (i = 0; i < n_bufs; i++) {
  334. size_t j;
  335. for (j = 0; j < bufs[i].n_planes; j++)
  336. get_dma_buf(bufs[i].dma_bufs[j]);
  337. }
  338. memcpy(intfs_copy, intfs, sizeof(intfs_copy[0]) * n_intfs);
  339. memcpy(bufs_copy, bufs, sizeof(bufs_copy[0]) * n_bufs);
  340. memcpy(custom_data_copy, custom_data, custom_data_size);
  341. ret = adf_device_post_nocopy(dev, intfs_copy, n_intfs, bufs_copy,
  342. n_bufs, custom_data_copy, custom_data_size);
  343. if (IS_ERR(ret))
  344. goto err_post;
  345. return ret;
  346. err_post:
  347. for (i = 0; i < n_bufs; i++) {
  348. size_t j;
  349. for (j = 0; j < bufs[i].n_planes; j++)
  350. dma_buf_put(bufs[i].dma_bufs[j]);
  351. }
  352. err_alloc:
  353. kfree(custom_data_copy);
  354. kfree(bufs_copy);
  355. kfree(intfs_copy);
  356. return ret;
  357. }
  358. EXPORT_SYMBOL(adf_device_post);
  359. /**
  360. * adf_device_post_nocopy - flip to a new set of buffers
  361. *
  362. * adf_device_post_nocopy() has the same behavior as adf_device_post(),
  363. * except ADF does not copy @intfs, @bufs, or @custom_data, and it does
  364. * not take an extra reference on the dma-bufs in @bufs.
  365. *
  366. * @intfs, @bufs, and @custom_data must point to buffers allocated by
  367. * kmalloc(). On success, ADF takes ownership of these buffers and the dma-bufs
  368. * in @bufs, and will kfree()/dma_buf_put() them when they are no longer needed.
  369. * On failure, adf_device_post_nocopy() does NOT take ownership of these
  370. * buffers or the dma-bufs, and the caller must clean them up.
  371. *
  372. * adf_device_post_nocopy() is mainly intended for implementing ADF's ioctls.
  373. * Clients may find the nocopy variant useful in limited cases, but most should
  374. * call adf_device_post() instead.
  375. */
  376. struct sync_fence *adf_device_post_nocopy(struct adf_device *dev,
  377. struct adf_interface **intfs, size_t n_intfs,
  378. struct adf_buffer *bufs, size_t n_bufs,
  379. void *custom_data, size_t custom_data_size)
  380. {
  381. struct adf_pending_post *cfg;
  382. struct adf_buffer_mapping *mappings;
  383. struct sync_fence *ret;
  384. size_t i;
  385. int err;
  386. cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
  387. if (!cfg)
  388. return ERR_PTR(-ENOMEM);
  389. mappings = kzalloc(sizeof(mappings[0]) * n_bufs, GFP_KERNEL);
  390. if (!mappings) {
  391. ret = ERR_PTR(-ENOMEM);
  392. goto err_alloc;
  393. }
  394. mutex_lock(&dev->client_lock);
  395. for (i = 0; i < n_bufs; i++) {
  396. err = adf_buffer_validate(&bufs[i]);
  397. if (err < 0) {
  398. ret = ERR_PTR(err);
  399. goto err_buf;
  400. }
  401. err = adf_buffer_map(dev, &bufs[i], &mappings[i]);
  402. if (err < 0) {
  403. ret = ERR_PTR(err);
  404. goto err_buf;
  405. }
  406. }
  407. INIT_LIST_HEAD(&cfg->head);
  408. cfg->config.n_bufs = n_bufs;
  409. cfg->config.bufs = bufs;
  410. cfg->config.mappings = mappings;
  411. cfg->config.custom_data = custom_data;
  412. cfg->config.custom_data_size = custom_data_size;
  413. err = dev->ops->validate(dev, &cfg->config, &cfg->state);
  414. if (err < 0) {
  415. ret = ERR_PTR(err);
  416. goto err_buf;
  417. }
  418. mutex_lock(&dev->post_lock);
  419. if (dev->ops->complete_fence)
  420. ret = dev->ops->complete_fence(dev, &cfg->config,
  421. cfg->state);
  422. else
  423. ret = adf_sw_complete_fence(dev);
  424. if (IS_ERR(ret))
  425. goto err_fence;
  426. list_add_tail(&cfg->head, &dev->post_list);
  427. queue_kthread_work(&dev->post_worker, &dev->post_work);
  428. mutex_unlock(&dev->post_lock);
  429. mutex_unlock(&dev->client_lock);
  430. kfree(intfs);
  431. return ret;
  432. err_fence:
  433. mutex_unlock(&dev->post_lock);
  434. err_buf:
  435. for (i = 0; i < n_bufs; i++)
  436. adf_buffer_mapping_cleanup(&mappings[i], &bufs[i]);
  437. mutex_unlock(&dev->client_lock);
  438. kfree(mappings);
  439. err_alloc:
  440. kfree(cfg);
  441. return ret;
  442. }
  443. EXPORT_SYMBOL(adf_device_post_nocopy);
  444. static void adf_attachment_list_to_array(struct adf_device *dev,
  445. struct list_head *src, struct adf_attachment *dst, size_t size)
  446. {
  447. struct adf_attachment_list *entry;
  448. size_t i = 0;
  449. if (!dst)
  450. return;
  451. list_for_each_entry(entry, src, head) {
  452. if (i == size)
  453. return;
  454. dst[i] = entry->attachment;
  455. i++;
  456. }
  457. }
  458. /**
  459. * adf_device_attachments - get device's list of active attachments
  460. *
  461. * @dev: the device
  462. * @attachments: storage for the attachment list (optional)
  463. * @n_attachments: length of @attachments
  464. *
  465. * If @attachments is not NULL, adf_device_attachments() will copy up to
  466. * @n_attachments entries into @attachments.
  467. *
  468. * Returns the length of the active attachment list.
  469. */
  470. size_t adf_device_attachments(struct adf_device *dev,
  471. struct adf_attachment *attachments, size_t n_attachments)
  472. {
  473. size_t retval;
  474. mutex_lock(&dev->client_lock);
  475. adf_attachment_list_to_array(dev, &dev->attached, attachments,
  476. n_attachments);
  477. retval = dev->n_attached;
  478. mutex_unlock(&dev->client_lock);
  479. return retval;
  480. }
  481. EXPORT_SYMBOL(adf_device_attachments);
  482. /**
  483. * adf_device_attachments_allowed - get device's list of allowed attachments
  484. *
  485. * @dev: the device
  486. * @attachments: storage for the attachment list (optional)
  487. * @n_attachments: length of @attachments
  488. *
  489. * If @attachments is not NULL, adf_device_attachments_allowed() will copy up to
  490. * @n_attachments entries into @attachments.
  491. *
  492. * Returns the length of the allowed attachment list.
  493. */
  494. size_t adf_device_attachments_allowed(struct adf_device *dev,
  495. struct adf_attachment *attachments, size_t n_attachments)
  496. {
  497. size_t retval;
  498. mutex_lock(&dev->client_lock);
  499. adf_attachment_list_to_array(dev, &dev->attach_allowed, attachments,
  500. n_attachments);
  501. retval = dev->n_attach_allowed;
  502. mutex_unlock(&dev->client_lock);
  503. return retval;
  504. }
  505. EXPORT_SYMBOL(adf_device_attachments_allowed);
  506. /**
  507. * adf_device_attached - return whether an overlay engine and interface are
  508. * attached
  509. *
  510. * @dev: the parent device
  511. * @eng: the overlay engine
  512. * @intf: the interface
  513. */
  514. bool adf_device_attached(struct adf_device *dev, struct adf_overlay_engine *eng,
  515. struct adf_interface *intf)
  516. {
  517. struct adf_attachment_list *attachment;
  518. mutex_lock(&dev->client_lock);
  519. attachment = adf_attachment_find(&dev->attached, eng, intf);
  520. mutex_unlock(&dev->client_lock);
  521. return attachment != NULL;
  522. }
  523. EXPORT_SYMBOL(adf_device_attached);
  524. /**
  525. * adf_device_attach_allowed - return whether the ADF device supports attaching
  526. * an overlay engine and interface
  527. *
  528. * @dev: the parent device
  529. * @eng: the overlay engine
  530. * @intf: the interface
  531. */
  532. bool adf_device_attach_allowed(struct adf_device *dev,
  533. struct adf_overlay_engine *eng, struct adf_interface *intf)
  534. {
  535. struct adf_attachment_list *attachment;
  536. mutex_lock(&dev->client_lock);
  537. attachment = adf_attachment_find(&dev->attach_allowed, eng, intf);
  538. mutex_unlock(&dev->client_lock);
  539. return attachment != NULL;
  540. }
  541. EXPORT_SYMBOL(adf_device_attach_allowed);
  542. /**
  543. * adf_device_attach - attach an overlay engine to an interface
  544. *
  545. * @dev: the parent device
  546. * @eng: the overlay engine
  547. * @intf: the interface
  548. *
  549. * Returns 0 on success, -%EINVAL if attaching @intf and @eng is not allowed,
  550. * -%EALREADY if @intf and @eng are already attached, or -errno on any other
  551. * failure.
  552. */
  553. int adf_device_attach(struct adf_device *dev, struct adf_overlay_engine *eng,
  554. struct adf_interface *intf)
  555. {
  556. int ret;
  557. struct adf_attachment_list *attachment = NULL;
  558. ret = adf_attachment_validate(dev, eng, intf);
  559. if (ret < 0)
  560. return ret;
  561. mutex_lock(&dev->client_lock);
  562. if (dev->n_attached == ADF_MAX_ATTACHMENTS) {
  563. ret = -ENOMEM;
  564. goto done;
  565. }
  566. if (!adf_attachment_find(&dev->attach_allowed, eng, intf)) {
  567. ret = -EINVAL;
  568. goto done;
  569. }
  570. if (adf_attachment_find(&dev->attached, eng, intf)) {
  571. ret = -EALREADY;
  572. goto done;
  573. }
  574. ret = adf_device_attach_op(dev, eng, intf);
  575. if (ret < 0)
  576. goto done;
  577. attachment = kzalloc(sizeof(*attachment), GFP_KERNEL);
  578. if (!attachment) {
  579. ret = -ENOMEM;
  580. goto done;
  581. }
  582. attachment->attachment.interface = intf;
  583. attachment->attachment.overlay_engine = eng;
  584. list_add_tail(&attachment->head, &dev->attached);
  585. dev->n_attached++;
  586. done:
  587. mutex_unlock(&dev->client_lock);
  588. if (ret < 0)
  589. kfree(attachment);
  590. return ret;
  591. }
  592. EXPORT_SYMBOL(adf_device_attach);
  593. /**
  594. * adf_device_detach - detach an overlay engine from an interface
  595. *
  596. * @dev: the parent device
  597. * @eng: the overlay engine
  598. * @intf: the interface
  599. *
  600. * Returns 0 on success, -%EINVAL if @intf and @eng are not attached,
  601. * or -errno on any other failure.
  602. */
  603. int adf_device_detach(struct adf_device *dev, struct adf_overlay_engine *eng,
  604. struct adf_interface *intf)
  605. {
  606. int ret;
  607. struct adf_attachment_list *attachment;
  608. ret = adf_attachment_validate(dev, eng, intf);
  609. if (ret < 0)
  610. return ret;
  611. mutex_lock(&dev->client_lock);
  612. attachment = adf_attachment_find(&dev->attached, eng, intf);
  613. if (!attachment) {
  614. ret = -EINVAL;
  615. goto done;
  616. }
  617. ret = adf_device_detach_op(dev, eng, intf);
  618. if (ret < 0)
  619. goto done;
  620. adf_attachment_free(attachment);
  621. dev->n_attached--;
  622. done:
  623. mutex_unlock(&dev->client_lock);
  624. return ret;
  625. }
  626. EXPORT_SYMBOL(adf_device_detach);
  627. /**
  628. * adf_interface_simple_buffer_alloc - allocate a simple buffer
  629. *
  630. * @intf: target interface
  631. * @w: width in pixels
  632. * @h: height in pixels
  633. * @format: format fourcc
  634. * @dma_buf: returns the allocated buffer
  635. * @offset: returns the byte offset of the allocated buffer's first pixel
  636. * @pitch: returns the allocated buffer's pitch
  637. *
  638. * See &struct adf_simple_buffer_alloc for a description of simple buffers and
  639. * their limitations.
  640. *
  641. * Returns 0 on success or -errno on failure.
  642. */
  643. int adf_interface_simple_buffer_alloc(struct adf_interface *intf, u16 w, u16 h,
  644. u32 format, struct dma_buf **dma_buf, u32 *offset, u32 *pitch)
  645. {
  646. if (!intf->ops || !intf->ops->alloc_simple_buffer)
  647. return -EOPNOTSUPP;
  648. if (!adf_format_is_rgb(format))
  649. return -EINVAL;
  650. return intf->ops->alloc_simple_buffer(intf, w, h, format, dma_buf,
  651. offset, pitch);
  652. }
  653. EXPORT_SYMBOL(adf_interface_simple_buffer_alloc);
  654. /**
  655. * adf_interface_simple_post - flip to a single buffer
  656. *
  657. * @intf: interface targeted by the flip
  658. * @buf: buffer to display
  659. *
  660. * adf_interface_simple_post() can be used generically for simple display
  661. * configurations, since the client does not need to provide any driver-private
  662. * configuration data.
  663. *
  664. * adf_interface_simple_post() has the same copying semantics as
  665. * adf_device_post().
  666. *
  667. * On success, returns a sync fence which signals when the buffer is removed
  668. * from the screen. On failure, returns ERR_PTR(-errno).
  669. */
  670. struct sync_fence *adf_interface_simple_post(struct adf_interface *intf,
  671. struct adf_buffer *buf)
  672. {
  673. size_t custom_data_size = 0;
  674. void *custom_data = NULL;
  675. struct sync_fence *ret;
  676. if (intf->ops && intf->ops->describe_simple_post) {
  677. int err;
  678. custom_data = kzalloc(ADF_MAX_CUSTOM_DATA_SIZE, GFP_KERNEL);
  679. if (!custom_data) {
  680. ret = ERR_PTR(-ENOMEM);
  681. goto done;
  682. }
  683. err = intf->ops->describe_simple_post(intf, buf, custom_data,
  684. &custom_data_size);
  685. if (err < 0) {
  686. ret = ERR_PTR(err);
  687. goto done;
  688. }
  689. }
  690. ret = adf_device_post(adf_interface_parent(intf), &intf, 1, buf, 1,
  691. custom_data, custom_data_size);
  692. done:
  693. kfree(custom_data);
  694. return ret;
  695. }
  696. EXPORT_SYMBOL(adf_interface_simple_post);