tree:
git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git lr/ariel
head: 72a56aed020b1fb0249195324c4f80a0cf25d72a
commit: 750e5383c2de328a6e79cf84b46b3ce31e9106a5 [8/63] Merge remote-tracking branch
'xo/lr/gud2' into merged
config: xtensa-allyesconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O
~/bin/make.cross
chmod +x ~/bin/make.cross
git checkout 750e5383c2de328a6e79cf84b46b3ce31e9106a5
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=xtensa
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp(a)intel.com>
All errors (new ones prefixed by >>):
drivers/gpu/drm/gud/gud_drm_gadget.c: In function 'gud_drm_gadget_fini':
> drivers/gpu/drm/gud/gud_drm_gadget.c:1161:2: error: implicit
declaration of function 'backlight_put'; did you mean 'backlight_enable'?
[-Werror=implicit-function-declaration]
1161 |
backlight_put(gdg->backlight);
| ^~~~~~~~~~~~~
| backlight_enable
cc1: some warnings being treated as errors
#
https://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git/co...
git remote add lkundrak-linux-mmp
git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git
git fetch --no-tags lkundrak-linux-mmp lr/ariel
git checkout 750e5383c2de328a6e79cf84b46b3ce31e9106a5
vim +1161 drivers/gpu/drm/gud/gud_drm_gadget.c
364f31b46de06f1 Noralf Trønnes 2020-05-29 1 // SPDX-License-Identifier: GPL-2.0
364f31b46de06f1 Noralf Trønnes 2020-05-29 2 /*
364f31b46de06f1 Noralf Trønnes 2020-05-29 3 * Copyright 2020 Noralf Trønnes
364f31b46de06f1 Noralf Trønnes 2020-05-29 4 */
364f31b46de06f1 Noralf Trønnes 2020-05-29 5
364f31b46de06f1 Noralf Trønnes 2020-05-29 6 #include <linux/backlight.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 7 #include <linux/delay.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 8 #include <linux/lz4.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 9 #include <linux/module.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 10 #include <linux/slab.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 11 #include <linux/spinlock.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 12 #include <linux/string.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 13
364f31b46de06f1 Noralf Trønnes 2020-05-29 14 #include <drm/drm_client.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 15 #include <drm/drm_connector.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 16 #include <drm/drm_crtc.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 17 #include <drm/drm_fourcc.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 18 #include <drm/drm_mode_object.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 19 #include <drm/drm_plane.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 20 #include <drm/drm_rect.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 21 #include <drm/gud_drm.h>
364f31b46de06f1 Noralf Trønnes 2020-05-29 22
364f31b46de06f1 Noralf Trønnes 2020-05-29 23 #include "gud_drm_internal.h"
364f31b46de06f1 Noralf Trønnes 2020-05-29 24
364f31b46de06f1 Noralf Trønnes 2020-05-29 25 /*
364f31b46de06f1 Noralf Trønnes 2020-05-29 26 * Concurrency:
364f31b46de06f1 Noralf Trønnes 2020-05-29 27 * Calls into this module from f_gud_drm
are serialized and run in process
364f31b46de06f1 Noralf Trønnes 2020-05-29 28 * context except
gud_drm_gadget_ctrl_get() which is run in interrupt context.
364f31b46de06f1 Noralf Trønnes 2020-05-29 29 *
364f31b46de06f1 Noralf Trønnes 2020-05-29 30 * Termination:
364f31b46de06f1 Noralf Trønnes 2020-05-29 31 * A DRM client can not release itself,
only the DRM driver which resources the
364f31b46de06f1 Noralf Trønnes 2020-05-29 32 * client uses can do that.
364f31b46de06f1 Noralf Trønnes 2020-05-29 33 * This means that there are 2 paths to
stop the gadget function:
364f31b46de06f1 Noralf Trønnes 2020-05-29 34 * - Unregistering the DRM driver (module
unload)
364f31b46de06f1 Noralf Trønnes 2020-05-29 35 * - Disabling the USB gadget (configfs
unbind)
364f31b46de06f1 Noralf Trønnes 2020-05-29 36 *
364f31b46de06f1 Noralf Trønnes 2020-05-29 37 * A use counter protects the gadget
should the client go away. A kref is used
364f31b46de06f1 Noralf Trønnes 2020-05-29 38 * to control the release of the
gud_drm_gadget structure shared by the 2 actors.
364f31b46de06f1 Noralf Trønnes 2020-05-29 39 *
364f31b46de06f1 Noralf Trønnes 2020-05-29 40 * Backlight:
364f31b46de06f1 Noralf Trønnes 2020-05-29 41 * If there's a backlight device
it's attached to the first connector.
364f31b46de06f1 Noralf Trønnes 2020-05-29 42 */
364f31b46de06f1 Noralf Trønnes 2020-05-29 43
364f31b46de06f1 Noralf Trønnes 2020-05-29 44 struct gud_drm_gadget_connector {
364f31b46de06f1 Noralf Trønnes 2020-05-29 45 struct drm_connector *connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 46
364f31b46de06f1 Noralf Trønnes 2020-05-29 47 const struct gud_drm_property
*properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 48 unsigned int num_properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 49 const char *tv_mode_enum_names;
364f31b46de06f1 Noralf Trønnes 2020-05-29 50 unsigned int num_tv_mode_enum_names;
364f31b46de06f1 Noralf Trønnes 2020-05-29 51 struct backlight_device *backlight;
364f31b46de06f1 Noralf Trønnes 2020-05-29 52
364f31b46de06f1 Noralf Trønnes 2020-05-29 53 spinlock_t lock; /* Protects the
following members: */
364f31b46de06f1 Noralf Trønnes 2020-05-29 54 enum drm_connector_status status;
364f31b46de06f1 Noralf Trønnes 2020-05-29 55 unsigned int width_mm;
364f31b46de06f1 Noralf Trønnes 2020-05-29 56 unsigned int height_mm;
364f31b46de06f1 Noralf Trønnes 2020-05-29 57 struct gud_drm_display_mode *modes;
364f31b46de06f1 Noralf Trønnes 2020-05-29 58 unsigned int num_modes;
364f31b46de06f1 Noralf Trønnes 2020-05-29 59 void *edid;
364f31b46de06f1 Noralf Trønnes 2020-05-29 60 size_t edid_len;
364f31b46de06f1 Noralf Trønnes 2020-05-29 61 bool changed;
364f31b46de06f1 Noralf Trønnes 2020-05-29 62 };
364f31b46de06f1 Noralf Trønnes 2020-05-29 63
364f31b46de06f1 Noralf Trønnes 2020-05-29 64 struct gud_drm_gadget {
364f31b46de06f1 Noralf Trønnes 2020-05-29 65 struct kref refcount;
364f31b46de06f1 Noralf Trønnes 2020-05-29 66 refcount_t usecnt;
364f31b46de06f1 Noralf Trønnes 2020-05-29 67 struct drm_client_dev client;
364f31b46de06f1 Noralf Trønnes 2020-05-29 68 struct backlight_device *backlight;
364f31b46de06f1 Noralf Trønnes 2020-05-29 69
364f31b46de06f1 Noralf Trønnes 2020-05-29 70 const u32 *formats;
364f31b46de06f1 Noralf Trønnes 2020-05-29 71 unsigned int format_count;
364f31b46de06f1 Noralf Trønnes 2020-05-29 72
364f31b46de06f1 Noralf Trønnes 2020-05-29 73 const struct gud_drm_property
*properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 74 unsigned int num_properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 75
364f31b46de06f1 Noralf Trønnes 2020-05-29 76 struct gud_drm_gadget_connector
*connectors;
364f31b46de06f1 Noralf Trønnes 2020-05-29 77 unsigned int connector_count;
364f31b46de06f1 Noralf Trønnes 2020-05-29 78
364f31b46de06f1 Noralf Trønnes 2020-05-29 79 struct drm_rect set_buffer_rect;
364f31b46de06f1 Noralf Trønnes 2020-05-29 80 u32 set_buffer_length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 81 u8 set_buffer_compression;
364f31b46de06f1 Noralf Trønnes 2020-05-29 82 u32 set_buffer_compressed_length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 83
364f31b46de06f1 Noralf Trønnes 2020-05-29 84 struct drm_client_buffer *buffer;
364f31b46de06f1 Noralf Trønnes 2020-05-29 85 struct drm_client_buffer *buffer_check;
364f31b46de06f1 Noralf Trønnes 2020-05-29 86 u8 brightness;
364f31b46de06f1 Noralf Trønnes 2020-05-29 87 bool check_ok;
364f31b46de06f1 Noralf Trønnes 2020-05-29 88
364f31b46de06f1 Noralf Trønnes 2020-05-29 89 size_t max_buffer_size;
364f31b46de06f1 Noralf Trønnes 2020-05-29 90 void *work_buf;
364f31b46de06f1 Noralf Trønnes 2020-05-29 91 };
364f31b46de06f1 Noralf Trønnes 2020-05-29 92
364f31b46de06f1 Noralf Trønnes 2020-05-29 93 static int
gud_drm_gadget_probe_connector(struct gud_drm_gadget_connector *gconn)
364f31b46de06f1 Noralf Trønnes 2020-05-29 94 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 95 struct drm_connector *connector =
gconn->connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 96 struct gud_drm_display_mode *modes =
NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 97 struct drm_device *drm =
connector->dev;
364f31b46de06f1 Noralf Trønnes 2020-05-29 98 struct drm_display_mode *mode;
364f31b46de06f1 Noralf Trønnes 2020-05-29 99 void *edid_data, *edid = NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 100 unsigned int num_modes = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 101 size_t edid_len = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 102 unsigned long flags;
364f31b46de06f1 Noralf Trønnes 2020-05-29 103 unsigned int i = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 104 int ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 105
364f31b46de06f1 Noralf Trønnes 2020-05-29 106
mutex_lock(&drm->mode_config.mutex);
364f31b46de06f1 Noralf Trønnes 2020-05-29 107
364f31b46de06f1 Noralf Trønnes 2020-05-29 108
connector->funcs->fill_modes(connector,
364f31b46de06f1 Noralf Trønnes 2020-05-29 109 drm->mode_config.max_width,
364f31b46de06f1 Noralf Trønnes 2020-05-29 110
drm->mode_config.max_height);
364f31b46de06f1 Noralf Trønnes 2020-05-29 111
364f31b46de06f1 Noralf Trønnes 2020-05-29 112 list_for_each_entry(mode,
&connector->modes, head)
364f31b46de06f1 Noralf Trønnes 2020-05-29 113 num_modes++;
364f31b46de06f1 Noralf Trønnes 2020-05-29 114
364f31b46de06f1 Noralf Trønnes 2020-05-29 115 if (!num_modes)
364f31b46de06f1 Noralf Trønnes 2020-05-29 116 goto update;
364f31b46de06f1 Noralf Trønnes 2020-05-29 117
364f31b46de06f1 Noralf Trønnes 2020-05-29 118 modes = kmalloc_array(num_modes,
sizeof(*modes), GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 119 if (!modes) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 120 ret = -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 121 num_modes = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 122 goto update;
364f31b46de06f1 Noralf Trønnes 2020-05-29 123 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 124
364f31b46de06f1 Noralf Trønnes 2020-05-29 125 list_for_each_entry(mode,
&connector->modes, head)
364f31b46de06f1 Noralf Trønnes 2020-05-29 126
gud_drm_from_display_mode(&modes[i++], mode);
364f31b46de06f1 Noralf Trønnes 2020-05-29 127
364f31b46de06f1 Noralf Trønnes 2020-05-29 128 if (!connector->edid_blob_ptr)
364f31b46de06f1 Noralf Trønnes 2020-05-29 129 goto update;
364f31b46de06f1 Noralf Trønnes 2020-05-29 130
364f31b46de06f1 Noralf Trønnes 2020-05-29 131 edid_data =
connector->edid_blob_ptr->data;
364f31b46de06f1 Noralf Trønnes 2020-05-29 132 edid_len =
connector->edid_blob_ptr->length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 133 if (!edid_data || !edid_len) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 134 edid_len = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 135 goto update;
364f31b46de06f1 Noralf Trønnes 2020-05-29 136 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 137
364f31b46de06f1 Noralf Trønnes 2020-05-29 138 edid = kmemdup(edid_data, edid_len,
GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 139 if (!edid) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 140 ret = -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 141 edid_len = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 142 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 143
364f31b46de06f1 Noralf Trønnes 2020-05-29 144 update:
364f31b46de06f1 Noralf Trønnes 2020-05-29 145 spin_lock_irqsave(&gconn->lock,
flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 146 if (gconn->status !=
connector->status || gconn->num_modes != num_modes ||
364f31b46de06f1 Noralf Trønnes 2020-05-29 147 gconn->edid_len != edid_len ||
364f31b46de06f1 Noralf Trønnes 2020-05-29 148 (gconn->modes && modes
&& memcmp(gconn->modes, modes, num_modes * sizeof(*modes))) ||
364f31b46de06f1 Noralf Trønnes 2020-05-29 149 (gconn->edid && edid
&& memcmp(gconn->edid, edid, edid_len)))
364f31b46de06f1 Noralf Trønnes 2020-05-29 150 gconn->changed = true;
364f31b46de06f1 Noralf Trønnes 2020-05-29 151 swap(gconn->modes, modes);
364f31b46de06f1 Noralf Trønnes 2020-05-29 152 gconn->num_modes = num_modes;
364f31b46de06f1 Noralf Trønnes 2020-05-29 153 swap(gconn->edid, edid);
364f31b46de06f1 Noralf Trønnes 2020-05-29 154 gconn->edid_len = edid_len;
364f31b46de06f1 Noralf Trønnes 2020-05-29 155 gconn->width_mm =
connector->display_info.width_mm;
364f31b46de06f1 Noralf Trønnes 2020-05-29 156 gconn->height_mm =
connector->display_info.height_mm;
364f31b46de06f1 Noralf Trønnes 2020-05-29 157 gconn->status =
connector->status;
364f31b46de06f1 Noralf Trønnes 2020-05-29 158
spin_unlock_irqrestore(&gconn->lock, flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 159
364f31b46de06f1 Noralf Trønnes 2020-05-29 160
mutex_unlock(&drm->mode_config.mutex);
364f31b46de06f1 Noralf Trønnes 2020-05-29 161
364f31b46de06f1 Noralf Trønnes 2020-05-29 162 kfree(edid);
364f31b46de06f1 Noralf Trønnes 2020-05-29 163 kfree(modes);
364f31b46de06f1 Noralf Trønnes 2020-05-29 164
364f31b46de06f1 Noralf Trønnes 2020-05-29 165 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 166 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 167
364f31b46de06f1 Noralf Trønnes 2020-05-29 168 static void
gud_drm_gadget_probe_connectors(struct gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 169 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 170 unsigned int i;
364f31b46de06f1 Noralf Trønnes 2020-05-29 171
364f31b46de06f1 Noralf Trønnes 2020-05-29 172 for (i = 0; i <
gdg->connector_count; i++)
364f31b46de06f1 Noralf Trønnes 2020-05-29 173
gud_drm_gadget_probe_connector(&gdg->connectors[i]);
364f31b46de06f1 Noralf Trønnes 2020-05-29 174 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 175
364f31b46de06f1 Noralf Trønnes 2020-05-29 176 static bool
gud_drm_gadget_check_buffer(struct gud_drm_gadget *gdg,
364f31b46de06f1 Noralf Trønnes 2020-05-29 177 struct drm_client_buffer *buffer,
364f31b46de06f1 Noralf Trønnes 2020-05-29 178 struct drm_display_mode *mode,
364f31b46de06f1 Noralf Trønnes 2020-05-29 179 u32 format)
364f31b46de06f1 Noralf Trønnes 2020-05-29 180 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 181 struct drm_framebuffer *fb;
364f31b46de06f1 Noralf Trønnes 2020-05-29 182
364f31b46de06f1 Noralf Trønnes 2020-05-29 183 if (!buffer)
364f31b46de06f1 Noralf Trønnes 2020-05-29 184 return false;
364f31b46de06f1 Noralf Trønnes 2020-05-29 185
364f31b46de06f1 Noralf Trønnes 2020-05-29 186 fb = buffer->fb;
364f31b46de06f1 Noralf Trønnes 2020-05-29 187
364f31b46de06f1 Noralf Trønnes 2020-05-29 188 return fb->format->format ==
format &&
364f31b46de06f1 Noralf Trønnes 2020-05-29 189 fb->width == mode->hdisplay
&& fb->height == mode->vdisplay;
364f31b46de06f1 Noralf Trønnes 2020-05-29 190 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 191
364f31b46de06f1 Noralf Trønnes 2020-05-29 192 static bool
gud_drm_gadget_set_connector_property(struct drm_client_dev *client,
364f31b46de06f1 Noralf Trønnes 2020-05-29 193 struct drm_connector *connector,
364f31b46de06f1 Noralf Trønnes 2020-05-29 194 u16 prop, u64 val, int *ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 195 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 196 struct drm_mode_config *config =
&connector->dev->mode_config;
364f31b46de06f1 Noralf Trønnes 2020-05-29 197 struct drm_property *property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 198
364f31b46de06f1 Noralf Trønnes 2020-05-29 199 switch (prop) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 200 case
GUD_DRM_PROPERTY_TV_SELECT_SUBCONNECTOR:
364f31b46de06f1 Noralf Trønnes 2020-05-29 201 property =
config->tv_select_subconnector_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 202 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 203 case GUD_DRM_PROPERTY_TV_LEFT_MARGIN:
364f31b46de06f1 Noralf Trønnes 2020-05-29 204 property =
config->tv_left_margin_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 205 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 206 case GUD_DRM_PROPERTY_TV_RIGHT_MARGIN:
364f31b46de06f1 Noralf Trønnes 2020-05-29 207 property =
config->tv_right_margin_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 208 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 209 case GUD_DRM_PROPERTY_TV_TOP_MARGIN:
364f31b46de06f1 Noralf Trønnes 2020-05-29 210 property =
config->tv_top_margin_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 211 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 212 case GUD_DRM_PROPERTY_TV_BOTTOM_MARGIN:
364f31b46de06f1 Noralf Trønnes 2020-05-29 213 property =
config->tv_bottom_margin_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 214 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 215 case GUD_DRM_PROPERTY_TV_MODE:
364f31b46de06f1 Noralf Trønnes 2020-05-29 216 property =
config->tv_mode_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 217 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 218 case GUD_DRM_PROPERTY_TV_BRIGHTNESS:
364f31b46de06f1 Noralf Trønnes 2020-05-29 219 property =
config->tv_brightness_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 220 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 221 case GUD_DRM_PROPERTY_TV_CONTRAST:
364f31b46de06f1 Noralf Trønnes 2020-05-29 222 property =
config->tv_contrast_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 223 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 224 case
GUD_DRM_PROPERTY_TV_FLICKER_REDUCTION:
364f31b46de06f1 Noralf Trønnes 2020-05-29 225 property =
config->tv_flicker_reduction_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 226 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 227 case GUD_DRM_PROPERTY_TV_OVERSCAN:
364f31b46de06f1 Noralf Trønnes 2020-05-29 228 property =
config->tv_overscan_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 229 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 230 case GUD_DRM_PROPERTY_TV_SATURATION:
364f31b46de06f1 Noralf Trønnes 2020-05-29 231 property =
config->tv_saturation_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 232 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 233 case GUD_DRM_PROPERTY_TV_HUE:
364f31b46de06f1 Noralf Trønnes 2020-05-29 234 property = config->tv_hue_property;
364f31b46de06f1 Noralf Trønnes 2020-05-29 235 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 236 default:
364f31b46de06f1 Noralf Trønnes 2020-05-29 237 return false;
364f31b46de06f1 Noralf Trønnes 2020-05-29 238 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 239
364f31b46de06f1 Noralf Trønnes 2020-05-29 240 *ret =
drm_client_modeset_set_property(client, &connector->base, property, val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 241
364f31b46de06f1 Noralf Trønnes 2020-05-29 242 return true;
364f31b46de06f1 Noralf Trønnes 2020-05-29 243 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 244
364f31b46de06f1 Noralf Trønnes 2020-05-29 245 static int gud_drm_gadget_check(struct
gud_drm_gadget *gdg, struct gud_drm_req_set_state *req,
364f31b46de06f1 Noralf Trønnes 2020-05-29 246 size_t size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 247 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 248 struct drm_client_dev *client =
&gdg->client;
364f31b46de06f1 Noralf Trønnes 2020-05-29 249 u32 format =
le32_to_cpu(req->format);
364f31b46de06f1 Noralf Trønnes 2020-05-29 250 struct drm_client_buffer *buffer;
364f31b46de06f1 Noralf Trønnes 2020-05-29 251 struct drm_connector *connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 252 struct drm_display_mode mode;
364f31b46de06f1 Noralf Trønnes 2020-05-29 253 unsigned int i;
364f31b46de06f1 Noralf Trønnes 2020-05-29 254 void *vaddr;
364f31b46de06f1 Noralf Trønnes 2020-05-29 255 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 256
364f31b46de06f1 Noralf Trønnes 2020-05-29 257 if (size < sizeof(struct
gud_drm_req_set_state))
364f31b46de06f1 Noralf Trønnes 2020-05-29 258 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 259
364f31b46de06f1 Noralf Trønnes 2020-05-29 260 if (size != struct_size(req, properties,
req->num_properties))
364f31b46de06f1 Noralf Trønnes 2020-05-29 261 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 262
364f31b46de06f1 Noralf Trønnes 2020-05-29 263 memset(&mode, 0, sizeof(mode));
364f31b46de06f1 Noralf Trønnes 2020-05-29 264 gud_drm_to_display_mode(&mode,
&req->mode);
364f31b46de06f1 Noralf Trønnes 2020-05-29 265
364f31b46de06f1 Noralf Trønnes 2020-05-29 266 gdg->check_ok = false;
364f31b46de06f1 Noralf Trønnes 2020-05-29 267
364f31b46de06f1 Noralf Trønnes 2020-05-29 268 if (!mode.hdisplay || !format)
364f31b46de06f1 Noralf Trønnes 2020-05-29 269 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 270
364f31b46de06f1 Noralf Trønnes 2020-05-29 271 if (req->connector >=
gdg->connector_count)
364f31b46de06f1 Noralf Trønnes 2020-05-29 272 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 273
364f31b46de06f1 Noralf Trønnes 2020-05-29 274 connector =
gdg->connectors[req->connector].connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 275
364f31b46de06f1 Noralf Trønnes 2020-05-29 276 if (gdg->buffer_check) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 277
drm_client_framebuffer_delete(gdg->buffer_check);
364f31b46de06f1 Noralf Trønnes 2020-05-29 278 gdg->buffer_check = NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 279 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 280
364f31b46de06f1 Noralf Trønnes 2020-05-29 281 if (!gud_drm_gadget_check_buffer(gdg,
gdg->buffer, &mode, format)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 282 buffer =
drm_client_framebuffer_create(client, mode.hdisplay, mode.vdisplay,
364f31b46de06f1 Noralf Trønnes 2020-05-29 283 format);
364f31b46de06f1 Noralf Trønnes 2020-05-29 284 if (IS_ERR(buffer))
364f31b46de06f1 Noralf Trønnes 2020-05-29 285 return PTR_ERR(buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 286
364f31b46de06f1 Noralf Trønnes 2020-05-29 287 vaddr =
drm_client_buffer_vmap(buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 288 if (IS_ERR(vaddr)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 289
drm_client_framebuffer_delete(buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 290 return PTR_ERR(vaddr);
364f31b46de06f1 Noralf Trønnes 2020-05-29 291 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 292
364f31b46de06f1 Noralf Trønnes 2020-05-29 293 gdg->buffer_check = buffer;
364f31b46de06f1 Noralf Trønnes 2020-05-29 294 } else {
364f31b46de06f1 Noralf Trønnes 2020-05-29 295 buffer = gdg->buffer;
364f31b46de06f1 Noralf Trønnes 2020-05-29 296 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 297
364f31b46de06f1 Noralf Trønnes 2020-05-29 298 ret = drm_client_modeset_set(client,
connector, &mode, buffer->fb);
364f31b46de06f1 Noralf Trønnes 2020-05-29 299 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 300 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 301
364f31b46de06f1 Noralf Trønnes 2020-05-29 302 for (i = 0; i <
req->num_properties; i++) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 303 u16 prop =
le16_to_cpu(req->properties[i].prop);
364f31b46de06f1 Noralf Trønnes 2020-05-29 304 u64 val =
le64_to_cpu(req->properties[i].val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 305
364f31b46de06f1 Noralf Trønnes 2020-05-29 306 if
(gud_drm_gadget_set_connector_property(client, connector, prop, val, &ret)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 307 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 308 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 309 continue;
364f31b46de06f1 Noralf Trønnes 2020-05-29 310 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 311
364f31b46de06f1 Noralf Trønnes 2020-05-29 312 switch (prop) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 313 case
GUD_DRM_PROPERTY_BACKLIGHT_BRIGHTNESS:
364f31b46de06f1 Noralf Trønnes 2020-05-29 314 if (val > 100)
364f31b46de06f1 Noralf Trønnes 2020-05-29 315 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 316 gdg->brightness = val;
364f31b46de06f1 Noralf Trønnes 2020-05-29 317 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 318 case GUD_DRM_PROPERTY_ROTATION:
364f31b46de06f1 Noralf Trønnes 2020-05-29 319 ret =
drm_client_modeset_set_rotation(client, val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 320 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 321 default:
364f31b46de06f1 Noralf Trønnes 2020-05-29 322 pr_err("%s: Unknown property:
%u\n", __func__, prop);
364f31b46de06f1 Noralf Trønnes 2020-05-29 323 continue;
364f31b46de06f1 Noralf Trønnes 2020-05-29 324 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 325
364f31b46de06f1 Noralf Trønnes 2020-05-29 326 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 327 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 328 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 329
364f31b46de06f1 Noralf Trønnes 2020-05-29 330 ret =
drm_client_modeset_check(&gdg->client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 331 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 332 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 333
364f31b46de06f1 Noralf Trønnes 2020-05-29 334 gdg->check_ok = true;
364f31b46de06f1 Noralf Trønnes 2020-05-29 335
364f31b46de06f1 Noralf Trønnes 2020-05-29 336 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 337 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 338
364f31b46de06f1 Noralf Trønnes 2020-05-29 339 static int gud_drm_gadget_commit(struct
gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 340 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 341 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 342
364f31b46de06f1 Noralf Trønnes 2020-05-29 343 if (!gdg->check_ok)
364f31b46de06f1 Noralf Trønnes 2020-05-29 344 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 345
364f31b46de06f1 Noralf Trønnes 2020-05-29 346 if (gdg->backlight) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 347 int val, max_brightness =
gdg->backlight->props.max_brightness;
364f31b46de06f1 Noralf Trønnes 2020-05-29 348
364f31b46de06f1 Noralf Trønnes 2020-05-29 349 val =
DIV64_U64_ROUND_UP(gdg->brightness * max_brightness, 100);
364f31b46de06f1 Noralf Trønnes 2020-05-29 350 ret =
backlight_device_set_brightness(gdg->backlight, val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 351 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 352 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 353 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 354
364f31b46de06f1 Noralf Trønnes 2020-05-29 355 ret =
drm_client_modeset_commit(&gdg->client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 356 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 357 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 358
364f31b46de06f1 Noralf Trønnes 2020-05-29 359 if (gdg->buffer_check) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 360
drm_client_framebuffer_delete(gdg->buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 361 gdg->buffer = gdg->buffer_check;
364f31b46de06f1 Noralf Trønnes 2020-05-29 362 gdg->buffer_check = NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 363 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 364
364f31b46de06f1 Noralf Trønnes 2020-05-29 365 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 366 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 367
364f31b46de06f1 Noralf Trønnes 2020-05-29 368 static size_t
gud_drm_gadget_write_buffer_memcpy(struct drm_client_buffer *buffer,
364f31b46de06f1 Noralf Trønnes 2020-05-29 369 const void *src, size_t len,
364f31b46de06f1 Noralf Trønnes 2020-05-29 370 struct drm_rect *rect)
364f31b46de06f1 Noralf Trønnes 2020-05-29 371 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 372 unsigned int cpp =
buffer->fb->format->cpp[0];
364f31b46de06f1 Noralf Trønnes 2020-05-29 373 size_t dst_pitch =
buffer->fb->pitches[0];
364f31b46de06f1 Noralf Trønnes 2020-05-29 374 size_t src_pitch = drm_rect_width(rect)
* cpp;
364f31b46de06f1 Noralf Trønnes 2020-05-29 375 unsigned int y;
364f31b46de06f1 Noralf Trønnes 2020-05-29 376 void *dst;
364f31b46de06f1 Noralf Trønnes 2020-05-29 377
364f31b46de06f1 Noralf Trønnes 2020-05-29 378 /* Get the address, it's already
mapped */
364f31b46de06f1 Noralf Trønnes 2020-05-29 379 dst = drm_client_buffer_vmap(buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 380 dst += rect->y1 * dst_pitch;
364f31b46de06f1 Noralf Trønnes 2020-05-29 381 dst += rect->x1 * cpp;
364f31b46de06f1 Noralf Trønnes 2020-05-29 382
364f31b46de06f1 Noralf Trønnes 2020-05-29 383 for (y = 0; y < drm_rect_height(rect)
&& len; y++) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 384 src_pitch = min(src_pitch, len);
364f31b46de06f1 Noralf Trønnes 2020-05-29 385 memcpy(dst, src, src_pitch);
364f31b46de06f1 Noralf Trønnes 2020-05-29 386 src += src_pitch;
364f31b46de06f1 Noralf Trønnes 2020-05-29 387 dst += dst_pitch;
364f31b46de06f1 Noralf Trønnes 2020-05-29 388 len -= src_pitch;
364f31b46de06f1 Noralf Trønnes 2020-05-29 389 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 390
364f31b46de06f1 Noralf Trønnes 2020-05-29 391 return len;
364f31b46de06f1 Noralf Trønnes 2020-05-29 392 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 393
364f31b46de06f1 Noralf Trønnes 2020-05-29 394 static bool
gud_drm_gadget_check_rect(struct drm_client_buffer *buffer, struct drm_rect *rect)
364f31b46de06f1 Noralf Trønnes 2020-05-29 395 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 396 return buffer->fb &&
rect->x1 < rect->x2 && rect->y1 < rect->y2 &&
364f31b46de06f1 Noralf Trønnes 2020-05-29 397 rect->x2 <=
buffer->fb->width && rect->y2 <= buffer->fb->height;
364f31b46de06f1 Noralf Trønnes 2020-05-29 398 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 399
364f31b46de06f1 Noralf Trønnes 2020-05-29 400 int gud_drm_gadget_write_buffer(struct
gud_drm_gadget *gdg, const void *buf, size_t len)
364f31b46de06f1 Noralf Trønnes 2020-05-29 401 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 402 struct drm_client_buffer *buffer =
gdg->buffer ? gdg->buffer : gdg->buffer_check;
364f31b46de06f1 Noralf Trønnes 2020-05-29 403 struct drm_rect *rect =
&gdg->set_buffer_rect;
364f31b46de06f1 Noralf Trønnes 2020-05-29 404 u8 compression =
gdg->set_buffer_compression;
364f31b46de06f1 Noralf Trønnes 2020-05-29 405 struct drm_framebuffer *fb;
364f31b46de06f1 Noralf Trønnes 2020-05-29 406 size_t remain;
364f31b46de06f1 Noralf Trønnes 2020-05-29 407 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 408
364f31b46de06f1 Noralf Trønnes 2020-05-29 409 pr_debug("%s: len=%zu
compression=0x%x\n", __func__, len, compression);
364f31b46de06f1 Noralf Trønnes 2020-05-29 410
364f31b46de06f1 Noralf Trønnes 2020-05-29 411 if (WARN_ON_ONCE(!buffer))
364f31b46de06f1 Noralf Trønnes 2020-05-29 412 return -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 413
364f31b46de06f1 Noralf Trønnes 2020-05-29 414 if (!gud_drm_gadget_check_rect(buffer,
rect)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 415 pr_err("%s: Rectangle doesn't
fit: " DRM_RECT_FMT "\n",
364f31b46de06f1 Noralf Trønnes 2020-05-29 416 __func__, DRM_RECT_ARG(rect));
364f31b46de06f1 Noralf Trønnes 2020-05-29 417 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 418 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 419
364f31b46de06f1 Noralf Trønnes 2020-05-29 420 fb = buffer->fb;
364f31b46de06f1 Noralf Trønnes 2020-05-29 421
364f31b46de06f1 Noralf Trønnes 2020-05-29 422 if (compression &
GUD_DRM_COMPRESSION_LZ4) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 423 if (len !=
gdg->set_buffer_compressed_length) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 424 pr_err("%s: Buffer compressed len
differs: %zu != %zu\n",
364f31b46de06f1 Noralf Trønnes 2020-05-29 425 __func__, len,
gdg->set_buffer_compressed_length);
364f31b46de06f1 Noralf Trønnes 2020-05-29 426 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 427 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 428
364f31b46de06f1 Noralf Trønnes 2020-05-29 429 ret = LZ4_decompress_safe(buf,
gdg->work_buf, len, gdg->max_buffer_size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 430 if (ret < 0) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 431 pr_err("%s: Failed to decompress
buffer\n", __func__);
364f31b46de06f1 Noralf Trønnes 2020-05-29 432 return -EIO;
364f31b46de06f1 Noralf Trønnes 2020-05-29 433 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 434
364f31b46de06f1 Noralf Trønnes 2020-05-29 435 buf = gdg->work_buf;
364f31b46de06f1 Noralf Trønnes 2020-05-29 436 len = ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 437 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 438
364f31b46de06f1 Noralf Trønnes 2020-05-29 439 if (len != gdg->set_buffer_length) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 440 pr_err("%s: Buffer len differs:
%zu != %zu\n",
364f31b46de06f1 Noralf Trønnes 2020-05-29 441 __func__, len,
gdg->set_buffer_length);
364f31b46de06f1 Noralf Trønnes 2020-05-29 442 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 443 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 444
364f31b46de06f1 Noralf Trønnes 2020-05-29 445 if (len > (drm_rect_width(rect) *
drm_rect_height(rect) * fb->format->cpp[0])) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 446 pr_err("%s: Buffer is too big for
rectangle: " DRM_RECT_FMT " len=%zu\n",
364f31b46de06f1 Noralf Trønnes 2020-05-29 447 __func__, DRM_RECT_ARG(rect),
len);
364f31b46de06f1 Noralf Trønnes 2020-05-29 448 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 449 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 450
364f31b46de06f1 Noralf Trønnes 2020-05-29 451 remain =
gud_drm_gadget_write_buffer_memcpy(buffer, buf, len, rect);
364f31b46de06f1 Noralf Trønnes 2020-05-29 452 if (remain) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 453 pr_err("%s: Failed to write
buffer: remain=%zu\n", __func__, remain);
364f31b46de06f1 Noralf Trønnes 2020-05-29 454 return -EIO;
364f31b46de06f1 Noralf Trønnes 2020-05-29 455 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 456
364f31b46de06f1 Noralf Trønnes 2020-05-29 457 return
drm_client_framebuffer_flush(buffer, rect);
364f31b46de06f1 Noralf Trønnes 2020-05-29 458 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 459
EXPORT_SYMBOL(gud_drm_gadget_write_buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 460
364f31b46de06f1 Noralf Trønnes 2020-05-29 461 int gud_drm_gadget_set_buffer(struct
gud_drm_gadget *gdg, struct gud_drm_req_set_buffer *req)
364f31b46de06f1 Noralf Trønnes 2020-05-29 462 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 463 u32 compressed_length =
le32_to_cpu(req->compressed_length);
364f31b46de06f1 Noralf Trønnes 2020-05-29 464 u32 length =
le32_to_cpu(req->length);
364f31b46de06f1 Noralf Trønnes 2020-05-29 465 struct drm_client_buffer *buffer;
364f31b46de06f1 Noralf Trønnes 2020-05-29 466 struct drm_rect rect;
364f31b46de06f1 Noralf Trønnes 2020-05-29 467 int ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 468
364f31b46de06f1 Noralf Trønnes 2020-05-29 469 if
(!refcount_inc_not_zero(&gdg->usecnt))
364f31b46de06f1 Noralf Trønnes 2020-05-29 470 return -ENODEV;
364f31b46de06f1 Noralf Trønnes 2020-05-29 471
364f31b46de06f1 Noralf Trønnes 2020-05-29 472 buffer = gdg->buffer ? gdg->buffer
: gdg->buffer_check;
364f31b46de06f1 Noralf Trønnes 2020-05-29 473 if (!buffer) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 474 ret = -ENOENT;
364f31b46de06f1 Noralf Trønnes 2020-05-29 475 goto out;
364f31b46de06f1 Noralf Trønnes 2020-05-29 476 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 477
364f31b46de06f1 Noralf Trønnes 2020-05-29 478 drm_rect_init(&rect,
le32_to_cpu(req->x), le32_to_cpu(req->y),
364f31b46de06f1 Noralf Trønnes 2020-05-29 479 le32_to_cpu(req->width),
le32_to_cpu(req->height));
364f31b46de06f1 Noralf Trønnes 2020-05-29 480
364f31b46de06f1 Noralf Trønnes 2020-05-29 481 pr_debug("%s: " DRM_RECT_FMT
"\n", __func__, DRM_RECT_ARG(&rect));
364f31b46de06f1 Noralf Trønnes 2020-05-29 482
364f31b46de06f1 Noralf Trønnes 2020-05-29 483 if (!gud_drm_gadget_check_rect(buffer,
&rect)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 484 ret = -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 485 goto out;
364f31b46de06f1 Noralf Trønnes 2020-05-29 486 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 487
364f31b46de06f1 Noralf Trønnes 2020-05-29 488 if (req->compression &
~GUD_DRM_COMPRESSION_LZ4) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 489 ret = -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 490 goto out;
364f31b46de06f1 Noralf Trønnes 2020-05-29 491 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 492
364f31b46de06f1 Noralf Trønnes 2020-05-29 493 gdg->set_buffer_rect = rect;
364f31b46de06f1 Noralf Trønnes 2020-05-29 494 gdg->set_buffer_length = length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 495
364f31b46de06f1 Noralf Trønnes 2020-05-29 496 if (req->compression) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 497 if (!compressed_length) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 498 ret = -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 499 goto out;
364f31b46de06f1 Noralf Trønnes 2020-05-29 500 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 501 gdg->set_buffer_compression =
req->compression;
364f31b46de06f1 Noralf Trønnes 2020-05-29 502 gdg->set_buffer_compressed_length =
compressed_length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 503 length = compressed_length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 504 } else {
364f31b46de06f1 Noralf Trønnes 2020-05-29 505 gdg->set_buffer_compression = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 506 gdg->set_buffer_compressed_length =
0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 507 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 508 out:
364f31b46de06f1 Noralf Trønnes 2020-05-29 509 refcount_dec(&gdg->usecnt);
364f31b46de06f1 Noralf Trønnes 2020-05-29 510
364f31b46de06f1 Noralf Trønnes 2020-05-29 511 return ret ? ret : length;
364f31b46de06f1 Noralf Trønnes 2020-05-29 512 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 513
EXPORT_SYMBOL(gud_drm_gadget_set_buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 514
364f31b46de06f1 Noralf Trønnes 2020-05-29 515 static void
gud_drm_gadget_delete_buffers(struct gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 516 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 517
drm_client_framebuffer_delete(gdg->buffer_check);
364f31b46de06f1 Noralf Trønnes 2020-05-29 518
drm_client_framebuffer_delete(gdg->buffer);
364f31b46de06f1 Noralf Trønnes 2020-05-29 519 gdg->buffer_check = NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 520 gdg->buffer = NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 521 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 522
364f31b46de06f1 Noralf Trønnes 2020-05-29 523 int gud_drm_gadget_disable_pipe(struct
gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 524 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 525 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 526
364f31b46de06f1 Noralf Trønnes 2020-05-29 527 ret =
drm_client_modeset_disable(&gdg->client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 528 gud_drm_gadget_delete_buffers(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 529
364f31b46de06f1 Noralf Trønnes 2020-05-29 530 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 531 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 532
EXPORT_SYMBOL(gud_drm_gadget_disable_pipe);
364f31b46de06f1 Noralf Trønnes 2020-05-29 533
364f31b46de06f1 Noralf Trønnes 2020-05-29 534 static int
gud_drm_gadget_ctrl_get_display_descriptor(struct gud_drm_gadget *gdg, u16 value,
364f31b46de06f1 Noralf Trønnes 2020-05-29 535 void *data, size_t size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 536 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 537 struct drm_device *drm =
gdg->client.dev;
364f31b46de06f1 Noralf Trønnes 2020-05-29 538 struct gud_drm_display_descriptor desc;
364f31b46de06f1 Noralf Trønnes 2020-05-29 539 u8 type = value >> 8;
364f31b46de06f1 Noralf Trønnes 2020-05-29 540 u8 index = value & 0xff;
364f31b46de06f1 Noralf Trønnes 2020-05-29 541
364f31b46de06f1 Noralf Trønnes 2020-05-29 542 if (type != GUD_DRM_USB_DT_DISPLAY ||
index)
364f31b46de06f1 Noralf Trønnes 2020-05-29 543 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 544
364f31b46de06f1 Noralf Trønnes 2020-05-29 545 desc.bLength = sizeof(desc);
364f31b46de06f1 Noralf Trønnes 2020-05-29 546 desc.bDescriptorType =
GUD_DRM_USB_DT_DISPLAY;
364f31b46de06f1 Noralf Trønnes 2020-05-29 547
364f31b46de06f1 Noralf Trønnes 2020-05-29 548 desc.bVersion = 1;
364f31b46de06f1 Noralf Trønnes 2020-05-29 549 desc.bMaxBufferSizeOrder =
ilog2(gdg->max_buffer_size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 550 desc.bmFlags = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 551 desc.bCompression =
GUD_DRM_COMPRESSION_LZ4;
364f31b46de06f1 Noralf Trønnes 2020-05-29 552
364f31b46de06f1 Noralf Trønnes 2020-05-29 553 desc.dwMinWidth =
cpu_to_le32(drm->mode_config.min_width);
364f31b46de06f1 Noralf Trønnes 2020-05-29 554 desc.dwMaxWidth =
cpu_to_le32(drm->mode_config.max_width);
364f31b46de06f1 Noralf Trønnes 2020-05-29 555 desc.dwMinHeight =
cpu_to_le32(drm->mode_config.min_height);
364f31b46de06f1 Noralf Trønnes 2020-05-29 556 desc.dwMaxHeight =
cpu_to_le32(drm->mode_config.max_height);
364f31b46de06f1 Noralf Trønnes 2020-05-29 557 desc.bNumFormats =
gdg->format_count;
364f31b46de06f1 Noralf Trønnes 2020-05-29 558 desc.bNumProperties =
gdg->num_properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 559 desc.bNumConnectors =
gdg->connector_count;
364f31b46de06f1 Noralf Trønnes 2020-05-29 560
364f31b46de06f1 Noralf Trønnes 2020-05-29 561 size = min(size, sizeof(desc));
364f31b46de06f1 Noralf Trønnes 2020-05-29 562 memcpy(data, &desc, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 563
364f31b46de06f1 Noralf Trønnes 2020-05-29 564 return size;
364f31b46de06f1 Noralf Trønnes 2020-05-29 565 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 566
364f31b46de06f1 Noralf Trønnes 2020-05-29 567 static void
gud_drm_gadget_ctrl_get_formats(struct gud_drm_gadget *gdg, __le32 *formats)
364f31b46de06f1 Noralf Trønnes 2020-05-29 568 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 569 unsigned int i;
364f31b46de06f1 Noralf Trønnes 2020-05-29 570
364f31b46de06f1 Noralf Trønnes 2020-05-29 571 for (i = 0; i < gdg->format_count;
i++)
364f31b46de06f1 Noralf Trønnes 2020-05-29 572 formats[i] =
cpu_to_le32(gdg->formats[i]);
364f31b46de06f1 Noralf Trønnes 2020-05-29 573 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 574
364f31b46de06f1 Noralf Trønnes 2020-05-29 575 static int
gud_drm_gadget_ctrl_get_connector(struct gud_drm_gadget *gdg, unsigned int index,
364f31b46de06f1 Noralf Trønnes 2020-05-29 576 struct
gud_drm_req_get_connector *desc)
364f31b46de06f1 Noralf Trønnes 2020-05-29 577 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 578 struct gud_drm_gadget_connector *gconn;
364f31b46de06f1 Noralf Trønnes 2020-05-29 579
364f31b46de06f1 Noralf Trønnes 2020-05-29 580 if (index >=
gdg->connector_count)
364f31b46de06f1 Noralf Trønnes 2020-05-29 581 return -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 582
364f31b46de06f1 Noralf Trønnes 2020-05-29 583 memset(desc, 0, sizeof(*desc));
364f31b46de06f1 Noralf Trønnes 2020-05-29 584
364f31b46de06f1 Noralf Trønnes 2020-05-29 585 gconn = &gdg->connectors[index];
364f31b46de06f1 Noralf Trønnes 2020-05-29 586
364f31b46de06f1 Noralf Trønnes 2020-05-29 587 desc->connector_type =
gconn->connector->connector_type;
364f31b46de06f1 Noralf Trønnes 2020-05-29 588 desc->flags =
cpu_to_le32(GUD_DRM_CONNECTOR_FLAGS_POLL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 589 desc->num_properties =
gconn->num_properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 590
364f31b46de06f1 Noralf Trønnes 2020-05-29 591 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 592 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 593
364f31b46de06f1 Noralf Trønnes 2020-05-29 594 static struct gud_drm_gadget_connector *
364f31b46de06f1 Noralf Trønnes 2020-05-29 595 gud_drm_gadget_get_gconn(struct
gud_drm_gadget *gdg, unsigned int index)
364f31b46de06f1 Noralf Trønnes 2020-05-29 596 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 597 if (index >=
gdg->connector_count)
364f31b46de06f1 Noralf Trønnes 2020-05-29 598 return NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 599
364f31b46de06f1 Noralf Trønnes 2020-05-29 600 return &gdg->connectors[index];
364f31b46de06f1 Noralf Trønnes 2020-05-29 601 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 602
364f31b46de06f1 Noralf Trønnes 2020-05-29 603 static int
gud_drm_gadget_ctrl_get_connector_status(struct gud_drm_gadget *gdg, unsigned int index,
364f31b46de06f1 Noralf Trønnes 2020-05-29 604 struct
gud_drm_req_get_connector_status *status)
364f31b46de06f1 Noralf Trønnes 2020-05-29 605 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 606 struct gud_drm_gadget_connector *gconn;
364f31b46de06f1 Noralf Trønnes 2020-05-29 607 unsigned long flags;
364f31b46de06f1 Noralf Trønnes 2020-05-29 608
364f31b46de06f1 Noralf Trønnes 2020-05-29 609 gconn = gud_drm_gadget_get_gconn(gdg,
index);
364f31b46de06f1 Noralf Trønnes 2020-05-29 610 if (!gconn)
364f31b46de06f1 Noralf Trønnes 2020-05-29 611 return -ENOENT;
364f31b46de06f1 Noralf Trønnes 2020-05-29 612
364f31b46de06f1 Noralf Trønnes 2020-05-29 613 memset(status, 0, sizeof(*status));
364f31b46de06f1 Noralf Trønnes 2020-05-29 614
364f31b46de06f1 Noralf Trønnes 2020-05-29 615 spin_lock_irqsave(&gconn->lock,
flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 616 status->status = gconn->status;
364f31b46de06f1 Noralf Trønnes 2020-05-29 617 if (gconn->changed) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 618 status->status |=
GUD_DRM_CONNECTOR_STATUS_CHANGED;
364f31b46de06f1 Noralf Trønnes 2020-05-29 619 gconn->changed = false;
364f31b46de06f1 Noralf Trønnes 2020-05-29 620 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 621 if (gconn->num_modes)
364f31b46de06f1 Noralf Trønnes 2020-05-29 622 status->num_modes =
cpu_to_le16(gconn->num_modes);
364f31b46de06f1 Noralf Trønnes 2020-05-29 623 if (gconn->edid_len)
364f31b46de06f1 Noralf Trønnes 2020-05-29 624 status->edid_len =
cpu_to_le16(gconn->edid_len);
364f31b46de06f1 Noralf Trønnes 2020-05-29 625
spin_unlock_irqrestore(&gconn->lock, flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 626
364f31b46de06f1 Noralf Trønnes 2020-05-29 627 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 628 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 629
364f31b46de06f1 Noralf Trønnes 2020-05-29 630 /* This runs in interrupt context */
364f31b46de06f1 Noralf Trønnes 2020-05-29 631 int gud_drm_gadget_ctrl_get(struct
gud_drm_gadget *gdg, u8 request,
364f31b46de06f1 Noralf Trønnes 2020-05-29 632 u16 index, void *data, size_t
size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 633 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 634 struct gud_drm_gadget_connector *gconn;
364f31b46de06f1 Noralf Trønnes 2020-05-29 635 unsigned long flags;
364f31b46de06f1 Noralf Trønnes 2020-05-29 636 int ret = -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 637
364f31b46de06f1 Noralf Trønnes 2020-05-29 638 pr_debug("%s: request=0x%x index=%u
size=%zu\n", __func__, request, index, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 639
364f31b46de06f1 Noralf Trønnes 2020-05-29 640 if
(!refcount_inc_not_zero(&gdg->usecnt))
364f31b46de06f1 Noralf Trønnes 2020-05-29 641 return -ENODEV;
364f31b46de06f1 Noralf Trønnes 2020-05-29 642
364f31b46de06f1 Noralf Trønnes 2020-05-29 643 if (!size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 644 goto out;
364f31b46de06f1 Noralf Trønnes 2020-05-29 645
364f31b46de06f1 Noralf Trønnes 2020-05-29 646 switch (request) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 647 case USB_REQ_GET_DESCRIPTOR:
364f31b46de06f1 Noralf Trønnes 2020-05-29 648 ret =
gud_drm_gadget_ctrl_get_display_descriptor(gdg, index, data, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 649 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 650 case GUD_DRM_USB_REQ_GET_FORMATS:
364f31b46de06f1 Noralf Trønnes 2020-05-29 651 if (!index && size ==
gdg->format_count * sizeof(u32)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 652 gud_drm_gadget_ctrl_get_formats(gdg,
data);
364f31b46de06f1 Noralf Trønnes 2020-05-29 653 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 654 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 655 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 656 case GUD_DRM_USB_REQ_GET_PROPERTIES:
364f31b46de06f1 Noralf Trønnes 2020-05-29 657 if (!index && size ==
gdg->num_properties * sizeof(*gdg->properties)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 658 memcpy(data, gdg->properties,
size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 659 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 660 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 661 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 662 case GUD_DRM_USB_REQ_GET_CONNECTOR:
364f31b46de06f1 Noralf Trønnes 2020-05-29 663 if (size == sizeof(struct
gud_drm_req_get_connector))
364f31b46de06f1 Noralf Trønnes 2020-05-29 664 ret =
gud_drm_gadget_ctrl_get_connector(gdg, index, data);
364f31b46de06f1 Noralf Trønnes 2020-05-29 665 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 666 case
GUD_DRM_USB_REQ_GET_CONNECTOR_PROPERTIES:
364f31b46de06f1 Noralf Trønnes 2020-05-29 667 gconn = gud_drm_gadget_get_gconn(gdg,
index);
364f31b46de06f1 Noralf Trønnes 2020-05-29 668 if (gconn && size ==
gconn->num_properties * sizeof(*gconn->properties)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 669 memcpy(data, gconn->properties,
size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 670 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 671 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 672 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 673 case
GUD_DRM_USB_REQ_GET_CONNECTOR_TV_MODE_VALUES:
364f31b46de06f1 Noralf Trønnes 2020-05-29 674 gconn = gud_drm_gadget_get_gconn(gdg,
index);
364f31b46de06f1 Noralf Trønnes 2020-05-29 675 if (gconn && size ==
gconn->num_tv_mode_enum_names * DRM_PROP_NAME_LEN) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 676 memcpy(data,
gconn->tv_mode_enum_names, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 677 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 678 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 679 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 680 case
GUD_DRM_USB_REQ_GET_CONNECTOR_STATUS:
364f31b46de06f1 Noralf Trønnes 2020-05-29 681 if (size == sizeof(struct
gud_drm_req_get_connector_status))
364f31b46de06f1 Noralf Trønnes 2020-05-29 682 ret =
gud_drm_gadget_ctrl_get_connector_status(gdg, index, data);
364f31b46de06f1 Noralf Trønnes 2020-05-29 683 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 684 case
GUD_DRM_USB_REQ_GET_CONNECTOR_MODES:
364f31b46de06f1 Noralf Trønnes 2020-05-29 685 gconn = gud_drm_gadget_get_gconn(gdg,
index);
364f31b46de06f1 Noralf Trønnes 2020-05-29 686 spin_lock_irqsave(&gconn->lock,
flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 687 if (gconn && size ==
gconn->num_modes * sizeof(*gconn->modes)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 688 memcpy(data, gconn->modes, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 689 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 690 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 691
spin_unlock_irqrestore(&gconn->lock, flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 692 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 693 case
GUD_DRM_USB_REQ_GET_CONNECTOR_EDID:
364f31b46de06f1 Noralf Trønnes 2020-05-29 694 gconn = gud_drm_gadget_get_gconn(gdg,
index);
364f31b46de06f1 Noralf Trønnes 2020-05-29 695 spin_lock_irqsave(&gconn->lock,
flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 696 if (gconn && size ==
gconn->edid_len) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 697 memcpy(data, gconn->edid, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 698 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 699 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 700
spin_unlock_irqrestore(&gconn->lock, flags);
364f31b46de06f1 Noralf Trønnes 2020-05-29 701 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 702 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 703 out:
364f31b46de06f1 Noralf Trønnes 2020-05-29 704 refcount_dec(&gdg->usecnt);
364f31b46de06f1 Noralf Trønnes 2020-05-29 705
364f31b46de06f1 Noralf Trønnes 2020-05-29 706 return !ret ? size : ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 707 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 708 EXPORT_SYMBOL(gud_drm_gadget_ctrl_get);
364f31b46de06f1 Noralf Trønnes 2020-05-29 709
364f31b46de06f1 Noralf Trønnes 2020-05-29 710 int gud_drm_gadget_ctrl_set(struct
gud_drm_gadget *gdg, u8 request,
364f31b46de06f1 Noralf Trønnes 2020-05-29 711 u16 index, void *data, size_t
size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 712 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 713 struct gud_drm_gadget_connector *gconn;
364f31b46de06f1 Noralf Trønnes 2020-05-29 714 int dpms, ret = -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 715
364f31b46de06f1 Noralf Trønnes 2020-05-29 716 pr_debug("%s: request=0x%x index=%u
size=%zu\n", __func__, request, index, size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 717
364f31b46de06f1 Noralf Trønnes 2020-05-29 718 if
(!refcount_inc_not_zero(&gdg->usecnt))
364f31b46de06f1 Noralf Trønnes 2020-05-29 719 return -ENODEV;
364f31b46de06f1 Noralf Trønnes 2020-05-29 720
364f31b46de06f1 Noralf Trønnes 2020-05-29 721 switch (request) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 722 case
GUD_DRM_USB_REQ_SET_CONNECTOR_FORCE_DETECT:
364f31b46de06f1 Noralf Trønnes 2020-05-29 723 gconn = gud_drm_gadget_get_gconn(gdg,
index);
364f31b46de06f1 Noralf Trønnes 2020-05-29 724 if (gconn)
364f31b46de06f1 Noralf Trønnes 2020-05-29 725 ret =
gud_drm_gadget_probe_connector(gconn);
364f31b46de06f1 Noralf Trønnes 2020-05-29 726 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 727 case GUD_DRM_USB_REQ_SET_STATE_CHECK:
364f31b46de06f1 Noralf Trønnes 2020-05-29 728 ret = gud_drm_gadget_check(gdg, data,
size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 729 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 730 case GUD_DRM_USB_REQ_SET_STATE_COMMIT:
364f31b46de06f1 Noralf Trønnes 2020-05-29 731 if (!size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 732 ret = gud_drm_gadget_commit(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 733 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 734 case
GUD_DRM_USB_REQ_SET_CONTROLLER_ENABLE:
364f31b46de06f1 Noralf Trønnes 2020-05-29 735 if (size == sizeof(u8)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 736 if (*(u8 *)data == 0)
364f31b46de06f1 Noralf Trønnes 2020-05-29 737 ret =
gud_drm_gadget_disable_pipe(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 738 else
364f31b46de06f1 Noralf Trønnes 2020-05-29 739 ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 740 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 741 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 742 case
GUD_DRM_USB_REQ_SET_DISPLAY_ENABLE:
364f31b46de06f1 Noralf Trønnes 2020-05-29 743 if (size == sizeof(u8)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 744 dpms = *(u8 *)data ? DRM_MODE_DPMS_ON
: DRM_MODE_DPMS_OFF;
364f31b46de06f1 Noralf Trønnes 2020-05-29 745 ret =
drm_client_modeset_dpms(&gdg->client, dpms);
364f31b46de06f1 Noralf Trønnes 2020-05-29 746 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 747 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 748 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 749
364f31b46de06f1 Noralf Trønnes 2020-05-29 750 refcount_dec(&gdg->usecnt);
364f31b46de06f1 Noralf Trønnes 2020-05-29 751
364f31b46de06f1 Noralf Trønnes 2020-05-29 752 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 753 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 754 EXPORT_SYMBOL(gud_drm_gadget_ctrl_set);
364f31b46de06f1 Noralf Trønnes 2020-05-29 755
364f31b46de06f1 Noralf Trønnes 2020-05-29 756 static int
gud_drm_gadget_get_formats(struct gud_drm_gadget *gdg, u8 *max_cpp)
364f31b46de06f1 Noralf Trønnes 2020-05-29 757 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 758 struct drm_device *drm =
gdg->client.dev;
364f31b46de06f1 Noralf Trønnes 2020-05-29 759 struct drm_plane *plane;
364f31b46de06f1 Noralf Trønnes 2020-05-29 760 unsigned int i;
364f31b46de06f1 Noralf Trønnes 2020-05-29 761 u32 *formats;
364f31b46de06f1 Noralf Trønnes 2020-05-29 762 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 763
364f31b46de06f1 Noralf Trønnes 2020-05-29 764 *max_cpp = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 765
364f31b46de06f1 Noralf Trønnes 2020-05-29 766 drm_for_each_plane(plane, drm) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 767 if (plane->type ==
DRM_PLANE_TYPE_PRIMARY)
364f31b46de06f1 Noralf Trønnes 2020-05-29 768 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 769 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 770
364f31b46de06f1 Noralf Trønnes 2020-05-29 771 formats =
kcalloc(plane->format_count, sizeof(u32), GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 772 if (!formats)
364f31b46de06f1 Noralf Trønnes 2020-05-29 773 return -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 774
364f31b46de06f1 Noralf Trønnes 2020-05-29 775 for (i = 0; i <
plane->format_count; i++) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 776 const struct drm_format_info *fmt;
364f31b46de06f1 Noralf Trønnes 2020-05-29 777
364f31b46de06f1 Noralf Trønnes 2020-05-29 778 fmt =
drm_format_info(plane->format_types[i]);
364f31b46de06f1 Noralf Trønnes 2020-05-29 779 if (fmt->num_planes != 1)
364f31b46de06f1 Noralf Trønnes 2020-05-29 780 continue;
364f31b46de06f1 Noralf Trønnes 2020-05-29 781
364f31b46de06f1 Noralf Trønnes 2020-05-29 782 /*
364f31b46de06f1 Noralf Trønnes 2020-05-29 783 * Supporting 24-bit bpp would add
complexity so don't bother.
364f31b46de06f1 Noralf Trønnes 2020-05-29 784 * It's hardly used and compression
removes much of the gain.
364f31b46de06f1 Noralf Trønnes 2020-05-29 785 */
364f31b46de06f1 Noralf Trønnes 2020-05-29 786 if (fmt->cpp[0] == 3)
364f31b46de06f1 Noralf Trønnes 2020-05-29 787 continue;
364f31b46de06f1 Noralf Trønnes 2020-05-29 788
364f31b46de06f1 Noralf Trønnes 2020-05-29 789 if (*max_cpp < fmt->cpp[0])
364f31b46de06f1 Noralf Trønnes 2020-05-29 790 *max_cpp = fmt->cpp[0];
364f31b46de06f1 Noralf Trønnes 2020-05-29 791
364f31b46de06f1 Noralf Trønnes 2020-05-29 792 formats[gdg->format_count++] =
plane->format_types[i];
364f31b46de06f1 Noralf Trønnes 2020-05-29 793 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 794
364f31b46de06f1 Noralf Trønnes 2020-05-29 795 if (!gdg->format_count) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 796 ret = -ENOENT;
364f31b46de06f1 Noralf Trønnes 2020-05-29 797 goto err_free;
364f31b46de06f1 Noralf Trønnes 2020-05-29 798 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 799
364f31b46de06f1 Noralf Trønnes 2020-05-29 800 gdg->formats = formats;
364f31b46de06f1 Noralf Trønnes 2020-05-29 801
364f31b46de06f1 Noralf Trønnes 2020-05-29 802 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 803
364f31b46de06f1 Noralf Trønnes 2020-05-29 804 err_free:
364f31b46de06f1 Noralf Trønnes 2020-05-29 805 kfree(formats);
364f31b46de06f1 Noralf Trønnes 2020-05-29 806
364f31b46de06f1 Noralf Trønnes 2020-05-29 807 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 808 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 809
364f31b46de06f1 Noralf Trønnes 2020-05-29 810 static int
gud_drm_gadget_get_rotation_property(struct drm_device *drm, u16 *prop, u64 *val)
364f31b46de06f1 Noralf Trønnes 2020-05-29 811 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 812 struct drm_property_enum *prop_enum;
364f31b46de06f1 Noralf Trønnes 2020-05-29 813 struct drm_plane *plane;
364f31b46de06f1 Noralf Trønnes 2020-05-29 814 unsigned int num_props = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 815 u16 bitmask = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 816
364f31b46de06f1 Noralf Trønnes 2020-05-29 817 drm_for_each_plane(plane, drm) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 818 if (plane->type ==
DRM_PLANE_TYPE_PRIMARY)
364f31b46de06f1 Noralf Trønnes 2020-05-29 819 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 820 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 821
364f31b46de06f1 Noralf Trønnes 2020-05-29 822 if (!plane->rotation_property)
364f31b46de06f1 Noralf Trønnes 2020-05-29 823 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 824
364f31b46de06f1 Noralf Trønnes 2020-05-29 825 list_for_each_entry(prop_enum,
&plane->rotation_property->enum_list, head) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 826 num_props++;
364f31b46de06f1 Noralf Trønnes 2020-05-29 827 bitmask |= BIT(prop_enum->value);
364f31b46de06f1 Noralf Trønnes 2020-05-29 828 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 829
364f31b46de06f1 Noralf Trønnes 2020-05-29 830 *prop = GUD_DRM_PROPERTY_ROTATION;
364f31b46de06f1 Noralf Trønnes 2020-05-29 831 *val = bitmask;
364f31b46de06f1 Noralf Trønnes 2020-05-29 832
364f31b46de06f1 Noralf Trønnes 2020-05-29 833 return 1;
364f31b46de06f1 Noralf Trønnes 2020-05-29 834 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 835
364f31b46de06f1 Noralf Trønnes 2020-05-29 836 static int
gud_drm_gadget_get_properties(struct gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 837 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 838 struct gud_drm_property *properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 839 u16 prop;
364f31b46de06f1 Noralf Trønnes 2020-05-29 840 u64 val;
364f31b46de06f1 Noralf Trønnes 2020-05-29 841 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 842
364f31b46de06f1 Noralf Trønnes 2020-05-29 843 ret =
gud_drm_gadget_get_rotation_property(gdg->client.dev, &prop, &val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 844 if (ret <= 0)
364f31b46de06f1 Noralf Trønnes 2020-05-29 845 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 846
364f31b46de06f1 Noralf Trønnes 2020-05-29 847 properties = kcalloc(1,
sizeof(*properties), GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 848 if (!properties)
364f31b46de06f1 Noralf Trønnes 2020-05-29 849 return -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 850
364f31b46de06f1 Noralf Trønnes 2020-05-29 851 gdg->properties = properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 852 gdg->num_properties++;
364f31b46de06f1 Noralf Trønnes 2020-05-29 853
364f31b46de06f1 Noralf Trønnes 2020-05-29 854 properties[0].prop = cpu_to_le16(prop);
364f31b46de06f1 Noralf Trønnes 2020-05-29 855 properties[0].val = cpu_to_le64(val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 856
364f31b46de06f1 Noralf Trønnes 2020-05-29 857 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 858 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 859
364f31b46de06f1 Noralf Trønnes 2020-05-29 860 static int
gud_drm_gadget_get_connector_properties(struct gud_drm_gadget *gdg,
364f31b46de06f1 Noralf Trønnes 2020-05-29 861 struct gud_drm_gadget_connector
*gconn)
364f31b46de06f1 Noralf Trønnes 2020-05-29 862 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 863 struct drm_device *drm =
gdg->client.dev;
364f31b46de06f1 Noralf Trønnes 2020-05-29 864 struct drm_mode_config *config =
&drm->mode_config;
364f31b46de06f1 Noralf Trønnes 2020-05-29 865 struct drm_connector *connector =
gconn->connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 866 struct drm_object_properties *conn_props
= connector->base.properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 867 struct gud_drm_property *properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 868 unsigned int i, ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 869 u16 prop;
364f31b46de06f1 Noralf Trønnes 2020-05-29 870 u64 val;
364f31b46de06f1 Noralf Trønnes 2020-05-29 871
364f31b46de06f1 Noralf Trønnes 2020-05-29 872
mutex_lock(&drm->mode_config.mutex);
364f31b46de06f1 Noralf Trønnes 2020-05-29 873
364f31b46de06f1 Noralf Trønnes 2020-05-29 874 if (!conn_props->count)
364f31b46de06f1 Noralf Trønnes 2020-05-29 875 goto unlock;
364f31b46de06f1 Noralf Trønnes 2020-05-29 876
364f31b46de06f1 Noralf Trønnes 2020-05-29 877 /* Add room for possible backlight */
364f31b46de06f1 Noralf Trønnes 2020-05-29 878 properties =
kcalloc(conn_props->count + 1, sizeof(*properties), GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 879 if (!properties) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 880 ret = -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 881 goto unlock;
364f31b46de06f1 Noralf Trønnes 2020-05-29 882 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 883
364f31b46de06f1 Noralf Trønnes 2020-05-29 884 gconn->properties = properties;
364f31b46de06f1 Noralf Trønnes 2020-05-29 885
364f31b46de06f1 Noralf Trønnes 2020-05-29 886 for (i = 0; i < conn_props->count;
i++) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 887 struct drm_property *property =
conn_props->properties[i];
364f31b46de06f1 Noralf Trønnes 2020-05-29 888
364f31b46de06f1 Noralf Trønnes 2020-05-29 889 if (property ==
config->tv_select_subconnector_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 890 prop =
GUD_DRM_PROPERTY_TV_SELECT_SUBCONNECTOR;
364f31b46de06f1 Noralf Trønnes 2020-05-29 891 val =
connector->state->tv.subconnector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 892 } else if (property ==
config->tv_left_margin_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 893 prop =
GUD_DRM_PROPERTY_TV_LEFT_MARGIN;
364f31b46de06f1 Noralf Trønnes 2020-05-29 894 val =
connector->state->tv.margins.left;
364f31b46de06f1 Noralf Trønnes 2020-05-29 895 } else if (property ==
config->tv_right_margin_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 896 prop =
GUD_DRM_PROPERTY_TV_RIGHT_MARGIN;
364f31b46de06f1 Noralf Trønnes 2020-05-29 897 val =
connector->state->tv.margins.right;
364f31b46de06f1 Noralf Trønnes 2020-05-29 898 } else if (property ==
config->tv_top_margin_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 899 prop =
GUD_DRM_PROPERTY_TV_TOP_MARGIN;
364f31b46de06f1 Noralf Trønnes 2020-05-29 900 val =
connector->state->tv.margins.top;
364f31b46de06f1 Noralf Trønnes 2020-05-29 901 } else if (property ==
config->tv_bottom_margin_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 902 prop =
GUD_DRM_PROPERTY_TV_BOTTOM_MARGIN;
364f31b46de06f1 Noralf Trønnes 2020-05-29 903 val =
connector->state->tv.margins.bottom;
364f31b46de06f1 Noralf Trønnes 2020-05-29 904 } else if (property ==
config->tv_mode_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 905 struct drm_property_enum *prop_enum;
364f31b46de06f1 Noralf Trønnes 2020-05-29 906 char *buf;
364f31b46de06f1 Noralf Trønnes 2020-05-29 907
364f31b46de06f1 Noralf Trønnes 2020-05-29 908 list_for_each_entry(prop_enum,
&property->enum_list, head)
364f31b46de06f1 Noralf Trønnes 2020-05-29 909 gconn->num_tv_mode_enum_names++;
364f31b46de06f1 Noralf Trønnes 2020-05-29 910
364f31b46de06f1 Noralf Trønnes 2020-05-29 911 if
(WARN_ON(!gconn->num_tv_mode_enum_names)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 912 ret = -EINVAL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 913 goto unlock;
364f31b46de06f1 Noralf Trønnes 2020-05-29 914 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 915
364f31b46de06f1 Noralf Trønnes 2020-05-29 916 buf =
kcalloc(gconn->num_tv_mode_enum_names, DRM_PROP_NAME_LEN, GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 917 if (!buf) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 918 ret = -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 919 goto unlock;
364f31b46de06f1 Noralf Trønnes 2020-05-29 920 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 921
364f31b46de06f1 Noralf Trønnes 2020-05-29 922 gconn->tv_mode_enum_names = buf;
364f31b46de06f1 Noralf Trønnes 2020-05-29 923
364f31b46de06f1 Noralf Trønnes 2020-05-29 924 list_for_each_entry(prop_enum,
&property->enum_list, head) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 925 strncpy(buf, prop_enum->name,
DRM_PROP_NAME_LEN);
364f31b46de06f1 Noralf Trønnes 2020-05-29 926 buf += DRM_PROP_NAME_LEN;
364f31b46de06f1 Noralf Trønnes 2020-05-29 927 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 928
364f31b46de06f1 Noralf Trønnes 2020-05-29 929 prop = GUD_DRM_PROPERTY_TV_MODE;
364f31b46de06f1 Noralf Trønnes 2020-05-29 930 val =
connector->state->tv.mode;
364f31b46de06f1 Noralf Trønnes 2020-05-29 931 val |=
gconn->num_tv_mode_enum_names << GUD_DRM_USB_CONNECTOR_TV_MODE_NUM_SHIFT;
364f31b46de06f1 Noralf Trønnes 2020-05-29 932 } else if (property ==
config->tv_brightness_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 933 prop =
GUD_DRM_PROPERTY_TV_BRIGHTNESS;
364f31b46de06f1 Noralf Trønnes 2020-05-29 934 val =
connector->state->tv.brightness;
364f31b46de06f1 Noralf Trønnes 2020-05-29 935 } else if (property ==
config->tv_contrast_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 936 prop = GUD_DRM_PROPERTY_TV_CONTRAST;
364f31b46de06f1 Noralf Trønnes 2020-05-29 937 val =
connector->state->tv.contrast;
364f31b46de06f1 Noralf Trønnes 2020-05-29 938 } else if (property ==
config->tv_flicker_reduction_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 939 prop =
GUD_DRM_PROPERTY_TV_FLICKER_REDUCTION;
364f31b46de06f1 Noralf Trønnes 2020-05-29 940 val =
connector->state->tv.flicker_reduction;
364f31b46de06f1 Noralf Trønnes 2020-05-29 941 } else if (property ==
config->tv_overscan_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 942 prop = GUD_DRM_PROPERTY_TV_OVERSCAN;
364f31b46de06f1 Noralf Trønnes 2020-05-29 943 val =
connector->state->tv.overscan;
364f31b46de06f1 Noralf Trønnes 2020-05-29 944 } else if (property ==
config->tv_saturation_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 945 prop =
GUD_DRM_PROPERTY_TV_SATURATION;
364f31b46de06f1 Noralf Trønnes 2020-05-29 946 val =
connector->state->tv.saturation;
364f31b46de06f1 Noralf Trønnes 2020-05-29 947 } else if (property ==
config->tv_hue_property) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 948 prop = GUD_DRM_PROPERTY_TV_HUE;
364f31b46de06f1 Noralf Trønnes 2020-05-29 949 val = connector->state->tv.hue;
364f31b46de06f1 Noralf Trønnes 2020-05-29 950 } else {
364f31b46de06f1 Noralf Trønnes 2020-05-29 951 continue;
364f31b46de06f1 Noralf Trønnes 2020-05-29 952 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 953
364f31b46de06f1 Noralf Trønnes 2020-05-29 954
properties[gconn->num_properties].prop = cpu_to_le16(prop);
364f31b46de06f1 Noralf Trønnes 2020-05-29 955
properties[gconn->num_properties++].val = cpu_to_le64(val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 956 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 957
364f31b46de06f1 Noralf Trønnes 2020-05-29 958 if (!connector->index &&
gdg->backlight) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 959 struct backlight_properties *props =
&gdg->backlight->props;
364f31b46de06f1 Noralf Trønnes 2020-05-29 960
364f31b46de06f1 Noralf Trønnes 2020-05-29 961 prop =
GUD_DRM_PROPERTY_BACKLIGHT_BRIGHTNESS;
364f31b46de06f1 Noralf Trønnes 2020-05-29 962 val =
DIV64_U64_ROUND_UP(props->brightness * 100, props->max_brightness);
364f31b46de06f1 Noralf Trønnes 2020-05-29 963
properties[gconn->num_properties].prop = cpu_to_le16(prop);
364f31b46de06f1 Noralf Trønnes 2020-05-29 964
properties[gconn->num_properties++].val = cpu_to_le64(val);
364f31b46de06f1 Noralf Trønnes 2020-05-29 965 gconn->backlight =
gdg->backlight;
364f31b46de06f1 Noralf Trønnes 2020-05-29 966 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 967 unlock:
364f31b46de06f1 Noralf Trønnes 2020-05-29 968
mutex_unlock(&drm->mode_config.mutex);
364f31b46de06f1 Noralf Trønnes 2020-05-29 969
364f31b46de06f1 Noralf Trønnes 2020-05-29 970 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 971 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 972
364f31b46de06f1 Noralf Trønnes 2020-05-29 973 static int
gud_drm_gadget_get_connectors(struct gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 974 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 975 struct gud_drm_gadget_connector
*connectors = NULL;
364f31b46de06f1 Noralf Trønnes 2020-05-29 976 struct drm_connector_list_iter
conn_iter;
364f31b46de06f1 Noralf Trønnes 2020-05-29 977 struct drm_device *drm =
gdg->client.dev;
364f31b46de06f1 Noralf Trønnes 2020-05-29 978 unsigned int connector_count = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 979 struct drm_connector *connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 980 int ret = 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 981
364f31b46de06f1 Noralf Trønnes 2020-05-29 982 drm_connector_list_iter_begin(drm,
&conn_iter);
364f31b46de06f1 Noralf Trønnes 2020-05-29 983
drm_client_for_each_connector_iter(connector, &conn_iter) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 984 struct gud_drm_gadget_connector *tmp,
*gconn;
364f31b46de06f1 Noralf Trønnes 2020-05-29 985
364f31b46de06f1 Noralf Trønnes 2020-05-29 986 tmp = krealloc(connectors,
(connector_count + 1) * sizeof(*connectors),
364f31b46de06f1 Noralf Trønnes 2020-05-29 987 GFP_KERNEL | __GFP_ZERO);
364f31b46de06f1 Noralf Trønnes 2020-05-29 988 if (!tmp) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 989 ret = -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 990 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 991 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 992
364f31b46de06f1 Noralf Trønnes 2020-05-29 993 connectors = tmp;
364f31b46de06f1 Noralf Trønnes 2020-05-29 994 drm_connector_get(connector);
364f31b46de06f1 Noralf Trønnes 2020-05-29 995 gconn =
&connectors[connector_count++];
364f31b46de06f1 Noralf Trønnes 2020-05-29 996 gconn->connector = connector;
364f31b46de06f1 Noralf Trønnes 2020-05-29 997 spin_lock_init(&gconn->lock);
364f31b46de06f1 Noralf Trønnes 2020-05-29 998
364f31b46de06f1 Noralf Trønnes 2020-05-29 999 ret =
gud_drm_gadget_get_connector_properties(gdg, gconn);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1000 if (ret)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1001 break;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1002 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1003
drm_connector_list_iter_end(&conn_iter);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1004
364f31b46de06f1 Noralf Trønnes 2020-05-29 1005 gdg->connectors = connectors;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1006 gdg->connector_count =
connector_count;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1007
364f31b46de06f1 Noralf Trønnes 2020-05-29 1008 return ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1009 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1010
364f31b46de06f1 Noralf Trønnes 2020-05-29 1011 static void gud_drm_gadget_release(struct
kref *kref)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1012 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1013 struct gud_drm_gadget *gdg =
container_of(kref, struct gud_drm_gadget, refcount);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1014
364f31b46de06f1 Noralf Trønnes 2020-05-29 1015 kfree(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1016 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1017
364f31b46de06f1 Noralf Trønnes 2020-05-29 1018 static void gud_drm_gadget_put(struct
gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1019 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1020 kref_put(&gdg->refcount,
gud_drm_gadget_release);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1021 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1022
364f31b46de06f1 Noralf Trønnes 2020-05-29 1023 static void
gud_drm_gadget_client_unregister(struct drm_client_dev *client)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1024 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1025 struct gud_drm_gadget *gdg =
container_of(client, struct gud_drm_gadget, client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1026 int timeout = 10000 / 50;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1027 unsigned int i;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1028
364f31b46de06f1 Noralf Trønnes 2020-05-29 1029 /*
364f31b46de06f1 Noralf Trønnes 2020-05-29 1030 * If usecnt doesn't drop to zero,
try waiting for the gadget, but we
364f31b46de06f1 Noralf Trønnes 2020-05-29 1031 * can't block the DRM driver
forever. The worst case wait the gadget side
364f31b46de06f1 Noralf Trønnes 2020-05-29 1032 * can hit are tens of seconds through
the call to drm_client_modeset_commit().
364f31b46de06f1 Noralf Trønnes 2020-05-29 1033 */
364f31b46de06f1 Noralf Trønnes 2020-05-29 1034 if
(refcount_dec_and_test(&gdg->usecnt)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1035 for (; timeout &&
refcount_read(&gdg->usecnt); timeout--)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1036 msleep(50);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1037 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1038
364f31b46de06f1 Noralf Trønnes 2020-05-29 1039 if (!timeout) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1040 pr_err("%s: Timeout waiting for
gadget side, will leak memory\n", __func__);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1041 return;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1042 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1043
364f31b46de06f1 Noralf Trønnes 2020-05-29 1044 vfree(gdg->work_buf);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1045 kfree(gdg->formats);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1046 kfree(gdg->properties);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1047
364f31b46de06f1 Noralf Trønnes 2020-05-29 1048 for (i = 0; i <
gdg->connector_count; i++) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1049 struct gud_drm_gadget_connector *gconn
= &gdg->connectors[i];
364f31b46de06f1 Noralf Trønnes 2020-05-29 1050
364f31b46de06f1 Noralf Trønnes 2020-05-29 1051
drm_connector_put(gconn->connector);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1052 kfree(gconn->properties);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1053 kfree(gconn->tv_mode_enum_names);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1054 kfree(gconn->modes);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1055 kfree(gconn->edid);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1056 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1057 kfree(gdg->connectors);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1058
364f31b46de06f1 Noralf Trønnes 2020-05-29 1059 gud_drm_gadget_delete_buffers(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1060 drm_client_release(client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1061 gud_drm_gadget_put(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1062 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1063
364f31b46de06f1 Noralf Trønnes 2020-05-29 1064 static int
gud_drm_gadget_client_hotplug(struct drm_client_dev *client)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1065 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1066 struct gud_drm_gadget *gdg =
container_of(client, struct gud_drm_gadget, client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1067
364f31b46de06f1 Noralf Trønnes 2020-05-29 1068 gud_drm_gadget_probe_connectors(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1069
364f31b46de06f1 Noralf Trønnes 2020-05-29 1070 return 0;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1071 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1072
364f31b46de06f1 Noralf Trønnes 2020-05-29 1073 static const struct drm_client_funcs
gdg_client_funcs = {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1074 .owner = THIS_MODULE,
364f31b46de06f1 Noralf Trønnes 2020-05-29 1075 .unregister =
gud_drm_gadget_client_unregister,
364f31b46de06f1 Noralf Trønnes 2020-05-29 1076 .hotplug =
gud_drm_gadget_client_hotplug,
364f31b46de06f1 Noralf Trønnes 2020-05-29 1077 };
364f31b46de06f1 Noralf Trønnes 2020-05-29 1078
364f31b46de06f1 Noralf Trønnes 2020-05-29 1079 struct gud_drm_gadget
*gud_drm_gadget_init(unsigned int minor_id, const char *backlight,
364f31b46de06f1 Noralf Trønnes 2020-05-29 1080 size_t *max_buffer_size)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1081 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1082 struct gud_drm_gadget *gdg;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1083 u8 max_cpp;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1084 int ret;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1085
364f31b46de06f1 Noralf Trønnes 2020-05-29 1086 gdg = kzalloc(sizeof(*gdg),
GFP_KERNEL);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1087 if (!gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1088 return ERR_PTR(-ENOMEM);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1089
364f31b46de06f1 Noralf Trønnes 2020-05-29 1090 ret = drm_client_init_from_id(minor_id,
&gdg->client, "gud-drm-gadget", &gdg_client_funcs);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1091 if (ret) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1092 pr_err("Failed to aquire
minor=%u\n", minor_id);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1093 kfree(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1094 return ERR_PTR(ret);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1095 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1096
364f31b46de06f1 Noralf Trønnes 2020-05-29 1097 refcount_set(&gdg->usecnt, 1);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1098 /* The DRM driver (through the client)
and f_gud_drm need one ref each */
364f31b46de06f1 Noralf Trønnes 2020-05-29 1099 kref_init(&gdg->refcount);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1100 kref_get(&gdg->refcount);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1101
364f31b46de06f1 Noralf Trønnes 2020-05-29 1102 if (backlight) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1103 gdg->backlight =
backlight_device_get_by_name(backlight);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1104 if (!gdg->backlight) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1105 pr_err("Failed to find backlight:
%s\n", backlight);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1106 ret = -ENODEV;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1107 goto error_release;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1108 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1109 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1110
364f31b46de06f1 Noralf Trønnes 2020-05-29 1111 ret = gud_drm_gadget_get_formats(gdg,
&max_cpp);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1112 if (ret) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1113 pr_err("Failed to get
formats\n");
364f31b46de06f1 Noralf Trønnes 2020-05-29 1114 goto error_release;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1115 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1116
364f31b46de06f1 Noralf Trønnes 2020-05-29 1117 *max_buffer_size =
gdg->client.dev->mode_config.max_width *
364f31b46de06f1 Noralf Trønnes 2020-05-29 1118
gdg->client.dev->mode_config.max_height * max_cpp;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1119 /* f_gud_drm will kmalloc a buffer of
this size */
364f31b46de06f1 Noralf Trønnes 2020-05-29 1120 *max_buffer_size = min_t(size_t,
*max_buffer_size, KMALLOC_MAX_SIZE);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1121
364f31b46de06f1 Noralf Trønnes 2020-05-29 1122 gdg->max_buffer_size =
*max_buffer_size;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1123 gdg->work_buf =
vmalloc(gdg->max_buffer_size);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1124 if (!gdg->work_buf) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1125 ret = -ENOMEM;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1126 goto error_release;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1127 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1128
364f31b46de06f1 Noralf Trønnes 2020-05-29 1129 ret =
gud_drm_gadget_get_properties(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1130 if (ret) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1131 pr_err("Failed to get
properties\n");
364f31b46de06f1 Noralf Trønnes 2020-05-29 1132 goto error_release;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1133 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1134
364f31b46de06f1 Noralf Trønnes 2020-05-29 1135 ret =
gud_drm_gadget_get_connectors(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1136 if (ret) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1137 pr_err("Failed to get
connectors\n");
364f31b46de06f1 Noralf Trønnes 2020-05-29 1138 goto error_release;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1139 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1140
364f31b46de06f1 Noralf Trønnes 2020-05-29 1141 if
(!drm_client_register(&gdg->client)) {
364f31b46de06f1 Noralf Trønnes 2020-05-29 1142 pr_err("DRM device is
gone\n");
364f31b46de06f1 Noralf Trønnes 2020-05-29 1143 ret = -ENODEV;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1144 goto error_release;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1145 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1146
364f31b46de06f1 Noralf Trønnes 2020-05-29 1147 gud_drm_gadget_probe_connectors(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1148
364f31b46de06f1 Noralf Trønnes 2020-05-29 1149 return gdg;
364f31b46de06f1 Noralf Trønnes 2020-05-29 1150
364f31b46de06f1 Noralf Trønnes 2020-05-29 1151 error_release:
364f31b46de06f1 Noralf Trønnes 2020-05-29 1152
gud_drm_gadget_client_unregister(&gdg->client);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1153 gud_drm_gadget_fini(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1154
364f31b46de06f1 Noralf Trønnes 2020-05-29 1155 return ERR_PTR(ret);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1156 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1157 EXPORT_SYMBOL(gud_drm_gadget_init);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1158
364f31b46de06f1 Noralf Trønnes 2020-05-29 1159 void gud_drm_gadget_fini(struct
gud_drm_gadget *gdg)
364f31b46de06f1 Noralf Trønnes 2020-05-29 1160 {
364f31b46de06f1 Noralf Trønnes 2020-05-29 @1161 backlight_put(gdg->backlight);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1162 gud_drm_gadget_put(gdg);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1163 }
364f31b46de06f1 Noralf Trønnes 2020-05-29 1164 EXPORT_SYMBOL(gud_drm_gadget_fini);
364f31b46de06f1 Noralf Trønnes 2020-05-29 1165
364f31b46de06f1 Noralf Trønnes 2020-05-29 1166 MODULE_AUTHOR("Noralf
Trønnes");
364f31b46de06f1 Noralf Trønnes 2020-05-29 1167 MODULE_LICENSE("GPL");
:::::: The code at line 1161 was first introduced by commit
:::::: 364f31b46de06f1ec6f1a5185f34aa385a7043ac drm/gud: Add functionality for the USB
gadget side
:::::: TO: Noralf Trønnes <noralf(a)tronnes.org>
:::::: CC: Lubomir Rintel <lkundrak(a)v3.sk>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org