Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/vkms: Allow to configure multiple encoders

Add a list of encoders to vkms_config and helper functions to add and
remove as many encoders as wanted.

For backwards compatibility, add one encoder to the default
configuration.

A future patch will allow to attach encoders and CRTCs, but for the
moment there are no changes in the way the output is configured.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Co-developed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250218101214.5790-12-jose.exposito89@gmail.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>

authored by

José Expósito and committed by
Maxime Ripard
f60a183d c204bf65

+195
+1
.clang-format
··· 691 691 - 'v4l2_m2m_for_each_src_buf_safe' 692 692 - 'virtio_device_for_each_vq' 693 693 - 'vkms_config_for_each_crtc' 694 + - 'vkms_config_for_each_encoder' 694 695 - 'vkms_config_for_each_plane' 695 696 - 'vkms_config_plane_for_each_possible_crtc' 696 697 - 'while_for_each_ftrace_op'
+94
drivers/gpu/drm/vkms/tests/vkms_config_test.c
··· 17 17 return count; 18 18 } 19 19 20 + static size_t vkms_config_get_num_encoders(struct vkms_config *config) 21 + { 22 + struct vkms_config_encoder *encoder_cfg; 23 + size_t count = 0; 24 + 25 + vkms_config_for_each_encoder(config, encoder_cfg) 26 + count++; 27 + 28 + return count; 29 + } 30 + 20 31 static struct vkms_config_plane *get_first_plane(struct vkms_config *config) 21 32 { 22 33 struct vkms_config_plane *plane_cfg; ··· 44 33 45 34 vkms_config_for_each_crtc(config, crtc_cfg) 46 35 return crtc_cfg; 36 + 37 + return NULL; 38 + } 39 + 40 + static struct vkms_config_encoder *get_first_encoder(struct vkms_config *config) 41 + { 42 + struct vkms_config_encoder *encoder_cfg; 43 + 44 + vkms_config_for_each_encoder(config, encoder_cfg) 45 + return encoder_cfg; 47 46 48 47 return NULL; 49 48 } ··· 78 57 79 58 KUNIT_EXPECT_EQ(test, vkms_config_get_num_planes(config), 0); 80 59 KUNIT_EXPECT_EQ(test, vkms_config_get_num_crtcs(config), 0); 60 + KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 0); 81 61 82 62 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); 83 63 ··· 151 129 } 152 130 KUNIT_EXPECT_EQ(test, n_possible_crtcs, 1); 153 131 } 132 + 133 + /* Encoders */ 134 + KUNIT_EXPECT_EQ(test, vkms_config_get_num_encoders(config), 1); 154 135 155 136 KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); 156 137 ··· 236 211 if (crtc_cfg != crtc_cfg1) 237 212 KUNIT_FAIL(test, "Unexpected CRTC"); 238 213 } 214 + 215 + vkms_config_destroy(config); 216 + } 217 + 218 + static void vkms_config_test_get_encoders(struct kunit *test) 219 + { 220 + struct vkms_config *config; 221 + struct vkms_config_encoder *encoder_cfg; 222 + struct vkms_config_encoder *encoder_cfg1, *encoder_cfg2; 223 + int n_encoders = 0; 224 + 225 + config = vkms_config_create("test"); 226 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); 227 + 228 + vkms_config_for_each_encoder(config, encoder_cfg) 229 + n_encoders++; 230 + KUNIT_ASSERT_EQ(test, n_encoders, 0); 231 + 232 + encoder_cfg1 = vkms_config_create_encoder(config); 233 + vkms_config_for_each_encoder(config, encoder_cfg) { 234 + n_encoders++; 235 + if (encoder_cfg != encoder_cfg1) 236 + KUNIT_FAIL(test, "Unexpected encoder"); 237 + } 238 + KUNIT_ASSERT_EQ(test, n_encoders, 1); 239 + n_encoders = 0; 240 + 241 + encoder_cfg2 = vkms_config_create_encoder(config); 242 + vkms_config_for_each_encoder(config, encoder_cfg) { 243 + n_encoders++; 244 + if (encoder_cfg != encoder_cfg1 && encoder_cfg != encoder_cfg2) 245 + KUNIT_FAIL(test, "Unexpected encoder"); 246 + } 247 + KUNIT_ASSERT_EQ(test, n_encoders, 2); 248 + n_encoders = 0; 249 + 250 + vkms_config_destroy_encoder(config, encoder_cfg2); 251 + vkms_config_for_each_encoder(config, encoder_cfg) { 252 + n_encoders++; 253 + if (encoder_cfg != encoder_cfg1) 254 + KUNIT_FAIL(test, "Unexpected encoder"); 255 + } 256 + KUNIT_ASSERT_EQ(test, n_encoders, 1); 257 + n_encoders = 0; 239 258 240 259 vkms_config_destroy(config); 241 260 } ··· 413 344 /* Invalid: Too many CRTCs */ 414 345 for (n = 0; n <= 32; n++) 415 346 vkms_config_create_crtc(config); 347 + 348 + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); 349 + 350 + vkms_config_destroy(config); 351 + } 352 + 353 + static void vkms_config_test_invalid_encoder_number(struct kunit *test) 354 + { 355 + struct vkms_config *config; 356 + struct vkms_config_encoder *encoder_cfg; 357 + int n; 358 + 359 + config = vkms_config_default_create(false, false, false); 360 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config); 361 + 362 + /* Invalid: No encoders */ 363 + encoder_cfg = get_first_encoder(config); 364 + vkms_config_destroy_encoder(config, encoder_cfg); 365 + KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); 366 + 367 + /* Invalid: Too many encoders */ 368 + for (n = 0; n <= 32; n++) 369 + vkms_config_create_encoder(config); 416 370 417 371 KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config)); 418 372 ··· 606 514 default_config_gen_params), 607 515 KUNIT_CASE(vkms_config_test_get_planes), 608 516 KUNIT_CASE(vkms_config_test_get_crtcs), 517 + KUNIT_CASE(vkms_config_test_get_encoders), 609 518 KUNIT_CASE(vkms_config_test_invalid_plane_number), 610 519 KUNIT_CASE(vkms_config_test_valid_plane_type), 611 520 KUNIT_CASE(vkms_config_test_valid_plane_possible_crtcs), 612 521 KUNIT_CASE(vkms_config_test_invalid_crtc_number), 522 + KUNIT_CASE(vkms_config_test_invalid_encoder_number), 613 523 KUNIT_CASE(vkms_config_test_attach_different_configs), 614 524 KUNIT_CASE(vkms_config_test_plane_attach_crtc), 615 525 KUNIT_CASE(vkms_config_test_plane_get_possible_crtcs),
+54
drivers/gpu/drm/vkms/vkms_config.c
··· 24 24 25 25 INIT_LIST_HEAD(&config->planes); 26 26 INIT_LIST_HEAD(&config->crtcs); 27 + INIT_LIST_HEAD(&config->encoders); 27 28 28 29 return config; 29 30 } ··· 37 36 struct vkms_config *config; 38 37 struct vkms_config_plane *plane_cfg; 39 38 struct vkms_config_crtc *crtc_cfg; 39 + struct vkms_config_encoder *encoder_cfg; 40 40 int n; 41 41 42 42 config = vkms_config_create(DEFAULT_DEVICE_NAME); ··· 82 80 goto err_alloc; 83 81 } 84 82 83 + encoder_cfg = vkms_config_create_encoder(config); 84 + if (IS_ERR(encoder_cfg)) 85 + goto err_alloc; 86 + 85 87 return config; 86 88 87 89 err_alloc: ··· 98 92 { 99 93 struct vkms_config_plane *plane_cfg, *plane_tmp; 100 94 struct vkms_config_crtc *crtc_cfg, *crtc_tmp; 95 + struct vkms_config_encoder *encoder_cfg, *encoder_tmp; 101 96 102 97 list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link) 103 98 vkms_config_destroy_plane(plane_cfg); 104 99 105 100 list_for_each_entry_safe(crtc_cfg, crtc_tmp, &config->crtcs, link) 106 101 vkms_config_destroy_crtc(config, crtc_cfg); 102 + 103 + list_for_each_entry_safe(encoder_cfg, encoder_tmp, &config->encoders, link) 104 + vkms_config_destroy_encoder(config, encoder_cfg); 107 105 108 106 kfree_const(config->dev_name); 109 107 kfree(config); ··· 202 192 return true; 203 193 } 204 194 195 + static bool valid_encoder_number(const struct vkms_config *config) 196 + { 197 + struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 198 + size_t n_encoders; 199 + 200 + n_encoders = list_count_nodes((struct list_head *)&config->encoders); 201 + if (n_encoders <= 0 || n_encoders >= 32) { 202 + drm_info(dev, "The number of encoders must be between 1 and 31\n"); 203 + return false; 204 + } 205 + 206 + return true; 207 + } 208 + 205 209 bool vkms_config_is_valid(const struct vkms_config *config) 206 210 { 207 211 struct vkms_config_crtc *crtc_cfg; ··· 224 200 return false; 225 201 226 202 if (!valid_crtc_number(config)) 203 + return false; 204 + 205 + if (!valid_encoder_number(config)) 227 206 return false; 228 207 229 208 if (!valid_plane_possible_crtcs(config)) ··· 249 222 const char *dev_name; 250 223 struct vkms_config_plane *plane_cfg; 251 224 struct vkms_config_crtc *crtc_cfg; 225 + struct vkms_config_encoder *encoder_cfg; 252 226 253 227 dev_name = vkms_config_get_device_name((struct vkms_config *)vkmsdev->config); 254 228 seq_printf(m, "dev_name=%s\n", dev_name); ··· 265 237 seq_printf(m, "\twriteback=%d\n", 266 238 vkms_config_crtc_get_writeback(crtc_cfg)); 267 239 } 240 + 241 + vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) 242 + seq_puts(m, "encoder\n"); 268 243 269 244 return 0; 270 245 } ··· 415 384 return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_CURSOR); 416 385 } 417 386 EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_cursor_plane); 387 + 388 + struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *config) 389 + { 390 + struct vkms_config_encoder *encoder_cfg; 391 + 392 + encoder_cfg = kzalloc(sizeof(*encoder_cfg), GFP_KERNEL); 393 + if (!encoder_cfg) 394 + return ERR_PTR(-ENOMEM); 395 + 396 + encoder_cfg->config = config; 397 + list_add_tail(&encoder_cfg->link, &config->encoders); 398 + 399 + return encoder_cfg; 400 + } 401 + EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); 402 + 403 + void vkms_config_destroy_encoder(struct vkms_config *config, 404 + struct vkms_config_encoder *encoder_cfg) 405 + { 406 + list_del(&encoder_cfg->link); 407 + kfree(encoder_cfg); 408 + } 409 + EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder);
+46
drivers/gpu/drm/vkms/vkms_config.h
··· 15 15 * @dev_name: Name of the device 16 16 * @planes: List of planes configured for the device 17 17 * @crtcs: List of CRTCs configured for the device 18 + * @encoders: List of encoders configured for the device 18 19 * @dev: Used to store the current VKMS device. Only set when the device is instantiated. 19 20 */ 20 21 struct vkms_config { 21 22 const char *dev_name; 22 23 struct list_head planes; 23 24 struct list_head crtcs; 25 + struct list_head encoders; 24 26 struct vkms_device *dev; 25 27 }; 26 28 ··· 72 70 }; 73 71 74 72 /** 73 + * struct vkms_config_encoder 74 + * 75 + * @link: Link to the others encoders in vkms_config 76 + * @config: The vkms_config this CRTC belongs to 77 + * @encoder: Internal usage. This pointer should never be considered as valid. 78 + * It can be used to store a temporary reference to a VKMS encoder 79 + * during device creation. This pointer is not managed by the 80 + * configuration and must be managed by other means. 81 + */ 82 + struct vkms_config_encoder { 83 + struct list_head link; 84 + struct vkms_config *config; 85 + 86 + /* Internal usage */ 87 + struct drm_encoder *encoder; 88 + }; 89 + 90 + /** 75 91 * vkms_config_for_each_plane - Iterate over the vkms_config planes 76 92 * @config: &struct vkms_config pointer 77 93 * @plane_cfg: &struct vkms_config_plane pointer used as cursor ··· 104 84 */ 105 85 #define vkms_config_for_each_crtc(config, crtc_cfg) \ 106 86 list_for_each_entry((crtc_cfg), &(config)->crtcs, link) 87 + 88 + /** 89 + * vkms_config_for_each_encoder - Iterate over the vkms_config encoders 90 + * @config: &struct vkms_config pointer 91 + * @encoder_cfg: &struct vkms_config_encoder pointer used as cursor 92 + */ 93 + #define vkms_config_for_each_encoder(config, encoder_cfg) \ 94 + list_for_each_entry((encoder_cfg), &(config)->encoders, link) 107 95 108 96 /** 109 97 * vkms_config_plane_for_each_possible_crtc - Iterate over the vkms_config_plane ··· 313 285 */ 314 286 struct vkms_config_plane *vkms_config_crtc_cursor_plane(const struct vkms_config *config, 315 287 struct vkms_config_crtc *crtc_cfg); 288 + 289 + /** 290 + * vkms_config_create_encoder() - Add a new encoder configuration 291 + * @config: Configuration to add the encoder to 292 + * 293 + * Returns: 294 + * The new encoder configuration or an error. Call vkms_config_destroy_encoder() 295 + * to free the returned encoder configuration. 296 + */ 297 + struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *config); 298 + 299 + /** 300 + * vkms_config_destroy_encoder() - Remove and free a encoder configuration 301 + * @config: Configuration to remove the encoder from 302 + * @encoder_cfg: Encoder configuration to destroy 303 + */ 304 + void vkms_config_destroy_encoder(struct vkms_config *config, 305 + struct vkms_config_encoder *encoder_cfg); 316 306 317 307 #endif /* _VKMS_CONFIG_H_ */