0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include <linux/usb.h>
0008
0009 #include <drm/drm_atomic_helper.h>
0010 #include <drm/drm_atomic_state_helper.h>
0011 #include <drm/drm_connector.h>
0012 #include <drm/drm_damage_helper.h>
0013 #include <drm/drm_drv.h>
0014 #include <drm/drm_edid.h>
0015 #include <drm/drm_fb_helper.h>
0016 #include <drm/drm_file.h>
0017 #include <drm/drm_format_helper.h>
0018 #include <drm/drm_fourcc.h>
0019 #include <drm/drm_framebuffer.h>
0020 #include <drm/drm_gem_atomic_helper.h>
0021 #include <drm/drm_gem_framebuffer_helper.h>
0022 #include <drm/drm_gem_shmem_helper.h>
0023 #include <drm/drm_ioctl.h>
0024 #include <drm/drm_managed.h>
0025 #include <drm/drm_modeset_helper_vtables.h>
0026 #include <drm/drm_probe_helper.h>
0027 #include <drm/drm_simple_kms_helper.h>
0028
0029 static bool eco_mode;
0030 module_param(eco_mode, bool, 0644);
0031 MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
0032
0033 #define DRIVER_NAME "gm12u320"
0034 #define DRIVER_DESC "Grain Media GM12U320 USB projector display"
0035 #define DRIVER_DATE "2019"
0036 #define DRIVER_MAJOR 1
0037 #define DRIVER_MINOR 0
0038
0039
0040
0041
0042
0043 #define GM12U320_USER_WIDTH 848
0044 #define GM12U320_REAL_WIDTH 854
0045 #define GM12U320_HEIGHT 480
0046
0047 #define GM12U320_BLOCK_COUNT 20
0048
0049 #define GM12U320_ERR(fmt, ...) \
0050 DRM_DEV_ERROR(gm12u320->dev.dev, fmt, ##__VA_ARGS__)
0051
0052 #define MISC_RCV_EPT 1
0053 #define DATA_RCV_EPT 2
0054 #define DATA_SND_EPT 3
0055 #define MISC_SND_EPT 4
0056
0057 #define DATA_BLOCK_HEADER_SIZE 84
0058 #define DATA_BLOCK_CONTENT_SIZE 64512
0059 #define DATA_BLOCK_FOOTER_SIZE 20
0060 #define DATA_BLOCK_SIZE (DATA_BLOCK_HEADER_SIZE + \
0061 DATA_BLOCK_CONTENT_SIZE + \
0062 DATA_BLOCK_FOOTER_SIZE)
0063 #define DATA_LAST_BLOCK_CONTENT_SIZE 4032
0064 #define DATA_LAST_BLOCK_SIZE (DATA_BLOCK_HEADER_SIZE + \
0065 DATA_LAST_BLOCK_CONTENT_SIZE + \
0066 DATA_BLOCK_FOOTER_SIZE)
0067
0068 #define CMD_SIZE 31
0069 #define READ_STATUS_SIZE 13
0070 #define MISC_VALUE_SIZE 4
0071
0072 #define CMD_TIMEOUT msecs_to_jiffies(200)
0073 #define DATA_TIMEOUT msecs_to_jiffies(1000)
0074 #define IDLE_TIMEOUT msecs_to_jiffies(2000)
0075 #define FIRST_FRAME_TIMEOUT msecs_to_jiffies(2000)
0076
0077 #define MISC_REQ_GET_SET_ECO_A 0xff
0078 #define MISC_REQ_GET_SET_ECO_B 0x35
0079
0080 #define MISC_REQ_UNKNOWN1_A 0xff
0081 #define MISC_REQ_UNKNOWN1_B 0x38
0082
0083 #define MISC_REQ_UNKNOWN2_A 0xa5
0084 #define MISC_REQ_UNKNOWN2_B 0x00
0085
0086 struct gm12u320_device {
0087 struct drm_device dev;
0088 struct device *dmadev;
0089 struct drm_simple_display_pipe pipe;
0090 struct drm_connector conn;
0091 unsigned char *cmd_buf;
0092 unsigned char *data_buf[GM12U320_BLOCK_COUNT];
0093 struct {
0094 struct delayed_work work;
0095 struct mutex lock;
0096 struct drm_framebuffer *fb;
0097 struct drm_rect rect;
0098 int frame;
0099 int draw_status_timeout;
0100 struct iosys_map src_map;
0101 } fb_update;
0102 };
0103
0104 #define to_gm12u320(__dev) container_of(__dev, struct gm12u320_device, dev)
0105
0106 static const char cmd_data[CMD_SIZE] = {
0107 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
0108 0x68, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff,
0109 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x80, 0x00,
0110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0111 };
0112
0113 static const char cmd_draw[CMD_SIZE] = {
0114 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
0115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe,
0116 0x00, 0x00, 0x00, 0xc0, 0xd1, 0x05, 0x00, 0x40,
0117 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
0118 };
0119
0120 static const char cmd_misc[CMD_SIZE] = {
0121 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
0122 0x04, 0x00, 0x00, 0x00, 0x80, 0x01, 0x10, 0xfd,
0123 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
0124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0125 };
0126
0127 static const char data_block_header[DATA_BLOCK_HEADER_SIZE] = {
0128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0136 0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0137 0x00, 0x04, 0x15, 0x00, 0x00, 0xfc, 0x00, 0x00,
0138 0x01, 0x00, 0x00, 0xdb
0139 };
0140
0141 static const char data_last_block_header[DATA_BLOCK_HEADER_SIZE] = {
0142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0150 0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0151 0x2a, 0x00, 0x20, 0x00, 0xc0, 0x0f, 0x00, 0x00,
0152 0x01, 0x00, 0x00, 0xd7
0153 };
0154
0155 static const char data_block_footer[DATA_BLOCK_FOOTER_SIZE] = {
0156 0xfb, 0x14, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
0157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0158 0x80, 0x00, 0x00, 0x4f
0159 };
0160
0161 static inline struct usb_device *gm12u320_to_usb_device(struct gm12u320_device *gm12u320)
0162 {
0163 return interface_to_usbdev(to_usb_interface(gm12u320->dev.dev));
0164 }
0165
0166 static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320)
0167 {
0168 int i, block_size;
0169 const char *hdr;
0170
0171 gm12u320->cmd_buf = drmm_kmalloc(&gm12u320->dev, CMD_SIZE, GFP_KERNEL);
0172 if (!gm12u320->cmd_buf)
0173 return -ENOMEM;
0174
0175 for (i = 0; i < GM12U320_BLOCK_COUNT; i++) {
0176 if (i == GM12U320_BLOCK_COUNT - 1) {
0177 block_size = DATA_LAST_BLOCK_SIZE;
0178 hdr = data_last_block_header;
0179 } else {
0180 block_size = DATA_BLOCK_SIZE;
0181 hdr = data_block_header;
0182 }
0183
0184 gm12u320->data_buf[i] = drmm_kzalloc(&gm12u320->dev,
0185 block_size, GFP_KERNEL);
0186 if (!gm12u320->data_buf[i])
0187 return -ENOMEM;
0188
0189 memcpy(gm12u320->data_buf[i], hdr, DATA_BLOCK_HEADER_SIZE);
0190 memcpy(gm12u320->data_buf[i] +
0191 (block_size - DATA_BLOCK_FOOTER_SIZE),
0192 data_block_footer, DATA_BLOCK_FOOTER_SIZE);
0193 }
0194
0195 return 0;
0196 }
0197
0198 static int gm12u320_misc_request(struct gm12u320_device *gm12u320,
0199 u8 req_a, u8 req_b,
0200 u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d)
0201 {
0202 struct usb_device *udev = gm12u320_to_usb_device(gm12u320);
0203 int ret, len;
0204
0205 memcpy(gm12u320->cmd_buf, &cmd_misc, CMD_SIZE);
0206 gm12u320->cmd_buf[20] = req_a;
0207 gm12u320->cmd_buf[21] = req_b;
0208 gm12u320->cmd_buf[22] = arg_a;
0209 gm12u320->cmd_buf[23] = arg_b;
0210 gm12u320->cmd_buf[24] = arg_c;
0211 gm12u320->cmd_buf[25] = arg_d;
0212
0213
0214 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, MISC_SND_EPT),
0215 gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
0216 if (ret || len != CMD_SIZE) {
0217 GM12U320_ERR("Misc. req. error %d\n", ret);
0218 return -EIO;
0219 }
0220
0221
0222 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, MISC_RCV_EPT),
0223 gm12u320->cmd_buf, MISC_VALUE_SIZE, &len,
0224 DATA_TIMEOUT);
0225 if (ret || len != MISC_VALUE_SIZE) {
0226 GM12U320_ERR("Misc. value error %d\n", ret);
0227 return -EIO;
0228 }
0229
0230
0231
0232 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, MISC_RCV_EPT),
0233 gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
0234 CMD_TIMEOUT);
0235 if (ret || len != READ_STATUS_SIZE) {
0236 GM12U320_ERR("Misc. status error %d\n", ret);
0237 return -EIO;
0238 }
0239
0240 return 0;
0241 }
0242
0243 static void gm12u320_32bpp_to_24bpp_packed(u8 *dst, u8 *src, int len)
0244 {
0245 while (len--) {
0246 *dst++ = *src++;
0247 *dst++ = *src++;
0248 *dst++ = *src++;
0249 src++;
0250 }
0251 }
0252
0253 static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
0254 {
0255 int block, dst_offset, len, remain, ret, x1, x2, y1, y2;
0256 struct drm_framebuffer *fb;
0257 void *vaddr;
0258 u8 *src;
0259
0260 mutex_lock(&gm12u320->fb_update.lock);
0261
0262 if (!gm12u320->fb_update.fb)
0263 goto unlock;
0264
0265 fb = gm12u320->fb_update.fb;
0266 x1 = gm12u320->fb_update.rect.x1;
0267 x2 = gm12u320->fb_update.rect.x2;
0268 y1 = gm12u320->fb_update.rect.y1;
0269 y2 = gm12u320->fb_update.rect.y2;
0270 vaddr = gm12u320->fb_update.src_map.vaddr;
0271
0272 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
0273 if (ret) {
0274 GM12U320_ERR("drm_gem_fb_begin_cpu_access err: %d\n", ret);
0275 goto put_fb;
0276 }
0277
0278 src = vaddr + y1 * fb->pitches[0] + x1 * 4;
0279
0280 x1 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
0281 x2 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2;
0282
0283 for (; y1 < y2; y1++) {
0284 remain = 0;
0285 len = (x2 - x1) * 3;
0286 dst_offset = (y1 * GM12U320_REAL_WIDTH + x1) * 3;
0287 block = dst_offset / DATA_BLOCK_CONTENT_SIZE;
0288 dst_offset %= DATA_BLOCK_CONTENT_SIZE;
0289
0290 if ((dst_offset + len) > DATA_BLOCK_CONTENT_SIZE) {
0291 remain = dst_offset + len - DATA_BLOCK_CONTENT_SIZE;
0292 len = DATA_BLOCK_CONTENT_SIZE - dst_offset;
0293 }
0294
0295 dst_offset += DATA_BLOCK_HEADER_SIZE;
0296 len /= 3;
0297
0298 gm12u320_32bpp_to_24bpp_packed(
0299 gm12u320->data_buf[block] + dst_offset,
0300 src, len);
0301
0302 if (remain) {
0303 block++;
0304 dst_offset = DATA_BLOCK_HEADER_SIZE;
0305 gm12u320_32bpp_to_24bpp_packed(
0306 gm12u320->data_buf[block] + dst_offset,
0307 src + len * 4, remain / 3);
0308 }
0309 src += fb->pitches[0];
0310 }
0311
0312 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
0313 put_fb:
0314 drm_framebuffer_put(fb);
0315 gm12u320->fb_update.fb = NULL;
0316 unlock:
0317 mutex_unlock(&gm12u320->fb_update.lock);
0318 }
0319
0320 static void gm12u320_fb_update_work(struct work_struct *work)
0321 {
0322 struct gm12u320_device *gm12u320 =
0323 container_of(to_delayed_work(work), struct gm12u320_device,
0324 fb_update.work);
0325 struct usb_device *udev = gm12u320_to_usb_device(gm12u320);
0326 int block, block_size, len;
0327 int ret = 0;
0328
0329 gm12u320_copy_fb_to_blocks(gm12u320);
0330
0331 for (block = 0; block < GM12U320_BLOCK_COUNT; block++) {
0332 if (block == GM12U320_BLOCK_COUNT - 1)
0333 block_size = DATA_LAST_BLOCK_SIZE;
0334 else
0335 block_size = DATA_BLOCK_SIZE;
0336
0337
0338 memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE);
0339 gm12u320->cmd_buf[8] = block_size & 0xff;
0340 gm12u320->cmd_buf[9] = block_size >> 8;
0341 gm12u320->cmd_buf[20] = 0xfc - block * 4;
0342 gm12u320->cmd_buf[21] =
0343 block | (gm12u320->fb_update.frame << 7);
0344
0345 ret = usb_bulk_msg(udev,
0346 usb_sndbulkpipe(udev, DATA_SND_EPT),
0347 gm12u320->cmd_buf, CMD_SIZE, &len,
0348 CMD_TIMEOUT);
0349 if (ret || len != CMD_SIZE)
0350 goto err;
0351
0352
0353 ret = usb_bulk_msg(udev,
0354 usb_sndbulkpipe(udev, DATA_SND_EPT),
0355 gm12u320->data_buf[block], block_size,
0356 &len, DATA_TIMEOUT);
0357 if (ret || len != block_size)
0358 goto err;
0359
0360
0361 ret = usb_bulk_msg(udev,
0362 usb_rcvbulkpipe(udev, DATA_RCV_EPT),
0363 gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
0364 CMD_TIMEOUT);
0365 if (ret || len != READ_STATUS_SIZE)
0366 goto err;
0367 }
0368
0369
0370 memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE);
0371 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, DATA_SND_EPT),
0372 gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT);
0373 if (ret || len != CMD_SIZE)
0374 goto err;
0375
0376
0377 ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, DATA_RCV_EPT),
0378 gm12u320->cmd_buf, READ_STATUS_SIZE, &len,
0379 gm12u320->fb_update.draw_status_timeout);
0380 if (ret || len != READ_STATUS_SIZE)
0381 goto err;
0382
0383 gm12u320->fb_update.draw_status_timeout = CMD_TIMEOUT;
0384 gm12u320->fb_update.frame = !gm12u320->fb_update.frame;
0385
0386
0387
0388
0389
0390 queue_delayed_work(system_long_wq, &gm12u320->fb_update.work,
0391 IDLE_TIMEOUT);
0392
0393 return;
0394 err:
0395
0396 if (ret != -ENODEV && ret != -ECONNRESET && ret != -ESHUTDOWN)
0397 GM12U320_ERR("Frame update error: %d\n", ret);
0398 }
0399
0400 static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb,
0401 const struct iosys_map *map,
0402 struct drm_rect *dirty)
0403 {
0404 struct gm12u320_device *gm12u320 = to_gm12u320(fb->dev);
0405 struct drm_framebuffer *old_fb = NULL;
0406 bool wakeup = false;
0407
0408 mutex_lock(&gm12u320->fb_update.lock);
0409
0410 if (gm12u320->fb_update.fb != fb) {
0411 old_fb = gm12u320->fb_update.fb;
0412 drm_framebuffer_get(fb);
0413 gm12u320->fb_update.fb = fb;
0414 gm12u320->fb_update.rect = *dirty;
0415 gm12u320->fb_update.src_map = *map;
0416 wakeup = true;
0417 } else {
0418 struct drm_rect *rect = &gm12u320->fb_update.rect;
0419
0420 rect->x1 = min(rect->x1, dirty->x1);
0421 rect->y1 = min(rect->y1, dirty->y1);
0422 rect->x2 = max(rect->x2, dirty->x2);
0423 rect->y2 = max(rect->y2, dirty->y2);
0424 }
0425
0426 mutex_unlock(&gm12u320->fb_update.lock);
0427
0428 if (wakeup)
0429 mod_delayed_work(system_long_wq, &gm12u320->fb_update.work, 0);
0430
0431 if (old_fb)
0432 drm_framebuffer_put(old_fb);
0433 }
0434
0435 static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320)
0436 {
0437 struct drm_framebuffer *old_fb;
0438
0439 cancel_delayed_work_sync(&gm12u320->fb_update.work);
0440
0441 mutex_lock(&gm12u320->fb_update.lock);
0442 old_fb = gm12u320->fb_update.fb;
0443 gm12u320->fb_update.fb = NULL;
0444 iosys_map_clear(&gm12u320->fb_update.src_map);
0445 mutex_unlock(&gm12u320->fb_update.lock);
0446
0447 drm_framebuffer_put(old_fb);
0448 }
0449
0450 static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320)
0451 {
0452 return gm12u320_misc_request(gm12u320, MISC_REQ_GET_SET_ECO_A,
0453 MISC_REQ_GET_SET_ECO_B, 0x01 ,
0454 eco_mode ? 0x01 : 0x00, 0x00, 0x01);
0455 }
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466 static struct edid gm12u320_edid = {
0467 .header = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 },
0468 .mfg_id = { 0x04, 0x72 },
0469 .prod_code = { 0x20, 0xc1 },
0470 .serial = 0xaa55aa55,
0471 .mfg_week = 1,
0472 .mfg_year = 16,
0473 .version = 1,
0474 .revision = 3,
0475 .input = 0x08,
0476 .features = 0x0a,
0477 .standard_timings = { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
0478 { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } },
0479 .detailed_timings = { {
0480 .pixel_clock = 3383,
0481
0482 .data.pixel_data.hactive_lo = 0x50,
0483 .data.pixel_data.hblank_lo = 0x00,
0484 .data.pixel_data.hactive_hblank_hi = 0x31,
0485
0486 .data.pixel_data.vactive_lo = 0xe0,
0487 .data.pixel_data.vblank_lo = 0x1c,
0488 .data.pixel_data.vactive_vblank_hi = 0x10,
0489
0490 .data.pixel_data.hsync_offset_lo = 0x28,
0491 .data.pixel_data.hsync_pulse_width_lo = 0x80,
0492 .data.pixel_data.vsync_offset_pulse_width_lo = 0x14,
0493 .data.pixel_data.hsync_vsync_offset_pulse_width_hi = 0x00,
0494
0495 .data.pixel_data.misc = 0x1e,
0496 }, {
0497 .pixel_clock = 0,
0498 .data.other_data.type = 0xfd,
0499 .data.other_data.data.range.min_vfreq = 59,
0500 .data.other_data.data.range.max_vfreq = 61,
0501 .data.other_data.data.range.min_hfreq_khz = 29,
0502 .data.other_data.data.range.max_hfreq_khz = 32,
0503 .data.other_data.data.range.pixel_clock_mhz = 4,
0504 .data.other_data.data.range.flags = 0,
0505 .data.other_data.data.range.formula.cvt = {
0506 0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
0507 }, {
0508 .pixel_clock = 0,
0509 .data.other_data.type = 0xfc,
0510 .data.other_data.data.str.str = {
0511 'P', 'r', 'o', 'j', 'e', 'c', 't', 'o', 'r', '\n',
0512 ' ', ' ', ' ' },
0513 }, {
0514 .pixel_clock = 0,
0515 .data.other_data.type = 0xfe,
0516 .data.other_data.data.str.str = {
0517 '\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
0518 ' ', ' ', ' ' },
0519 } },
0520 .checksum = 0x13,
0521 };
0522
0523 static int gm12u320_conn_get_modes(struct drm_connector *connector)
0524 {
0525 drm_connector_update_edid_property(connector, &gm12u320_edid);
0526 return drm_add_edid_modes(connector, &gm12u320_edid);
0527 }
0528
0529 static const struct drm_connector_helper_funcs gm12u320_conn_helper_funcs = {
0530 .get_modes = gm12u320_conn_get_modes,
0531 };
0532
0533 static const struct drm_connector_funcs gm12u320_conn_funcs = {
0534 .fill_modes = drm_helper_probe_single_connector_modes,
0535 .destroy = drm_connector_cleanup,
0536 .reset = drm_atomic_helper_connector_reset,
0537 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0538 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0539 };
0540
0541 static int gm12u320_conn_init(struct gm12u320_device *gm12u320)
0542 {
0543 drm_connector_helper_add(&gm12u320->conn, &gm12u320_conn_helper_funcs);
0544 return drm_connector_init(&gm12u320->dev, &gm12u320->conn,
0545 &gm12u320_conn_funcs, DRM_MODE_CONNECTOR_VGA);
0546 }
0547
0548
0549
0550
0551 static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe,
0552 struct drm_crtc_state *crtc_state,
0553 struct drm_plane_state *plane_state)
0554 {
0555 struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT };
0556 struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev);
0557 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
0558
0559 gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT;
0560 gm12u320_fb_mark_dirty(plane_state->fb, &shadow_plane_state->data[0], &rect);
0561 }
0562
0563 static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe)
0564 {
0565 struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev);
0566
0567 gm12u320_stop_fb_update(gm12u320);
0568 }
0569
0570 static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe,
0571 struct drm_plane_state *old_state)
0572 {
0573 struct drm_plane_state *state = pipe->plane.state;
0574 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
0575 struct drm_rect rect;
0576
0577 if (drm_atomic_helper_damage_merged(old_state, state, &rect))
0578 gm12u320_fb_mark_dirty(state->fb, &shadow_plane_state->data[0], &rect);
0579 }
0580
0581 static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = {
0582 .enable = gm12u320_pipe_enable,
0583 .disable = gm12u320_pipe_disable,
0584 .update = gm12u320_pipe_update,
0585 DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
0586 };
0587
0588 static const uint32_t gm12u320_pipe_formats[] = {
0589 DRM_FORMAT_XRGB8888,
0590 };
0591
0592 static const uint64_t gm12u320_pipe_modifiers[] = {
0593 DRM_FORMAT_MOD_LINEAR,
0594 DRM_FORMAT_MOD_INVALID
0595 };
0596
0597
0598
0599
0600
0601
0602 static struct drm_gem_object *gm12u320_gem_prime_import(struct drm_device *dev,
0603 struct dma_buf *dma_buf)
0604 {
0605 struct gm12u320_device *gm12u320 = to_gm12u320(dev);
0606
0607 if (!gm12u320->dmadev)
0608 return ERR_PTR(-ENODEV);
0609
0610 return drm_gem_prime_import_dev(dev, dma_buf, gm12u320->dmadev);
0611 }
0612
0613 DEFINE_DRM_GEM_FOPS(gm12u320_fops);
0614
0615 static const struct drm_driver gm12u320_drm_driver = {
0616 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
0617
0618 .name = DRIVER_NAME,
0619 .desc = DRIVER_DESC,
0620 .date = DRIVER_DATE,
0621 .major = DRIVER_MAJOR,
0622 .minor = DRIVER_MINOR,
0623
0624 .fops = &gm12u320_fops,
0625 DRM_GEM_SHMEM_DRIVER_OPS,
0626 .gem_prime_import = gm12u320_gem_prime_import,
0627 };
0628
0629 static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
0630 .fb_create = drm_gem_fb_create_with_dirty,
0631 .atomic_check = drm_atomic_helper_check,
0632 .atomic_commit = drm_atomic_helper_commit,
0633 };
0634
0635 static int gm12u320_usb_probe(struct usb_interface *interface,
0636 const struct usb_device_id *id)
0637 {
0638 struct gm12u320_device *gm12u320;
0639 struct drm_device *dev;
0640 int ret;
0641
0642
0643
0644
0645
0646 if (interface->cur_altsetting->desc.bInterfaceNumber != 0)
0647 return -ENODEV;
0648
0649 gm12u320 = devm_drm_dev_alloc(&interface->dev, &gm12u320_drm_driver,
0650 struct gm12u320_device, dev);
0651 if (IS_ERR(gm12u320))
0652 return PTR_ERR(gm12u320);
0653 dev = &gm12u320->dev;
0654
0655 gm12u320->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
0656 if (!gm12u320->dmadev)
0657 drm_warn(dev, "buffer sharing not supported");
0658
0659 INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
0660 mutex_init(&gm12u320->fb_update.lock);
0661
0662 ret = drmm_mode_config_init(dev);
0663 if (ret)
0664 goto err_put_device;
0665
0666 dev->mode_config.min_width = GM12U320_USER_WIDTH;
0667 dev->mode_config.max_width = GM12U320_USER_WIDTH;
0668 dev->mode_config.min_height = GM12U320_HEIGHT;
0669 dev->mode_config.max_height = GM12U320_HEIGHT;
0670 dev->mode_config.funcs = &gm12u320_mode_config_funcs;
0671
0672 ret = gm12u320_usb_alloc(gm12u320);
0673 if (ret)
0674 goto err_put_device;
0675
0676 ret = gm12u320_set_ecomode(gm12u320);
0677 if (ret)
0678 goto err_put_device;
0679
0680 ret = gm12u320_conn_init(gm12u320);
0681 if (ret)
0682 goto err_put_device;
0683
0684 ret = drm_simple_display_pipe_init(&gm12u320->dev,
0685 &gm12u320->pipe,
0686 &gm12u320_pipe_funcs,
0687 gm12u320_pipe_formats,
0688 ARRAY_SIZE(gm12u320_pipe_formats),
0689 gm12u320_pipe_modifiers,
0690 &gm12u320->conn);
0691 if (ret)
0692 goto err_put_device;
0693
0694 drm_mode_config_reset(dev);
0695
0696 usb_set_intfdata(interface, dev);
0697 ret = drm_dev_register(dev, 0);
0698 if (ret)
0699 goto err_put_device;
0700
0701 drm_fbdev_generic_setup(dev, 0);
0702
0703 return 0;
0704
0705 err_put_device:
0706 put_device(gm12u320->dmadev);
0707 return ret;
0708 }
0709
0710 static void gm12u320_usb_disconnect(struct usb_interface *interface)
0711 {
0712 struct drm_device *dev = usb_get_intfdata(interface);
0713 struct gm12u320_device *gm12u320 = to_gm12u320(dev);
0714
0715 put_device(gm12u320->dmadev);
0716 gm12u320->dmadev = NULL;
0717 drm_dev_unplug(dev);
0718 drm_atomic_helper_shutdown(dev);
0719 }
0720
0721 static __maybe_unused int gm12u320_suspend(struct usb_interface *interface,
0722 pm_message_t message)
0723 {
0724 struct drm_device *dev = usb_get_intfdata(interface);
0725
0726 return drm_mode_config_helper_suspend(dev);
0727 }
0728
0729 static __maybe_unused int gm12u320_resume(struct usb_interface *interface)
0730 {
0731 struct drm_device *dev = usb_get_intfdata(interface);
0732 struct gm12u320_device *gm12u320 = to_gm12u320(dev);
0733
0734 gm12u320_set_ecomode(gm12u320);
0735
0736 return drm_mode_config_helper_resume(dev);
0737 }
0738
0739 static const struct usb_device_id id_table[] = {
0740 { USB_DEVICE(0x1de1, 0xc102) },
0741 {},
0742 };
0743 MODULE_DEVICE_TABLE(usb, id_table);
0744
0745 static struct usb_driver gm12u320_usb_driver = {
0746 .name = "gm12u320",
0747 .probe = gm12u320_usb_probe,
0748 .disconnect = gm12u320_usb_disconnect,
0749 .id_table = id_table,
0750 #ifdef CONFIG_PM
0751 .suspend = gm12u320_suspend,
0752 .resume = gm12u320_resume,
0753 .reset_resume = gm12u320_resume,
0754 #endif
0755 };
0756
0757 module_usb_driver(gm12u320_usb_driver);
0758 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0759 MODULE_LICENSE("GPL");