2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
4 * YoungJun Cho <yj44.cho@samsung.com>
5 * Eunchul Kim <chulspro.kim@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundationr
12 #include <linux/kernel.h>
13 #include <linux/err.h>
14 #include <linux/interrupt.h>
16 #include <linux/platform_device.h>
17 #include <linux/clk.h>
18 #include <linux/pm_runtime.h>
21 #include <drm/exynos_drm.h>
22 #include "regs-rotator.h"
23 #include "exynos_drm.h"
24 #include "exynos_drm_drv.h"
25 #include "exynos_drm_ipp.h"
28 * Rotator supports image crop/rotator and input/output DMA operations.
29 * input DMA reads image data from the memory.
30 * output DMA writes image data to memory.
32 * M2M operation : supports crop/scale/rotation/csc so on.
33 * Memory ----> Rotator H/W ----> Memory.
38 * 1. check suspend/resume api if needed.
39 * 2. need to check use case platform_device_id.
40 * 3. check src/dst size with, height.
41 * 4. need to add supported list in prop_list.
44 #define get_rot_context(dev) platform_get_drvdata(to_platform_device(dev))
45 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
46 struct rot_context, ippdrv);
47 #define rot_read(offset) readl(rot->regs + (offset))
48 #define rot_write(cfg, offset) writel(cfg, rot->regs + (offset))
51 ROT_IRQ_STATUS_COMPLETE
= 8,
52 ROT_IRQ_STATUS_ILLEGAL
= 9,
56 * A structure of limitation.
58 * @min_w: minimum width.
59 * @min_h: minimum height.
60 * @max_w: maximum width.
61 * @max_h: maximum height.
73 * A structure of limitation table.
75 * @ycbcr420_2p: case of YUV.
76 * @rgb888: case of RGB.
78 struct rot_limit_table
{
79 struct rot_limit ycbcr420_2p
;
80 struct rot_limit rgb888
;
84 * A structure of rotator context.
85 * @ippdrv: prepare initialization using ippdrv.
86 * @regs_res: register resources.
87 * @regs: memory mapped io registers.
88 * @clock: rotator gate clock.
89 * @limit_tbl: limitation of rotator.
91 * @cur_buf_id: current operation buffer id.
92 * @suspended: suspended state.
95 struct exynos_drm_ippdrv ippdrv
;
96 struct resource
*regs_res
;
99 struct rot_limit_table
*limit_tbl
;
101 int cur_buf_id
[EXYNOS_DRM_OPS_MAX
];
105 static void rotator_reg_set_irq(struct rot_context
*rot
, bool enable
)
107 u32 val
= rot_read(ROT_CONFIG
);
110 val
|= ROT_CONFIG_IRQ
;
112 val
&= ~ROT_CONFIG_IRQ
;
114 rot_write(val
, ROT_CONFIG
);
117 static u32
rotator_reg_get_fmt(struct rot_context
*rot
)
119 u32 val
= rot_read(ROT_CONTROL
);
121 val
&= ROT_CONTROL_FMT_MASK
;
126 static enum rot_irq_status
rotator_reg_get_irq_status(struct rot_context
*rot
)
128 u32 val
= rot_read(ROT_STATUS
);
130 val
= ROT_STATUS_IRQ(val
);
132 if (val
== ROT_STATUS_IRQ_VAL_COMPLETE
)
133 return ROT_IRQ_STATUS_COMPLETE
;
135 return ROT_IRQ_STATUS_ILLEGAL
;
138 static irqreturn_t
rotator_irq_handler(int irq
, void *arg
)
140 struct rot_context
*rot
= arg
;
141 struct exynos_drm_ippdrv
*ippdrv
= &rot
->ippdrv
;
142 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
143 struct drm_exynos_ipp_event_work
*event_work
= c_node
->event_work
;
144 enum rot_irq_status irq_status
;
147 /* Get execution result */
148 irq_status
= rotator_reg_get_irq_status(rot
);
151 val
= rot_read(ROT_STATUS
);
152 val
|= ROT_STATUS_IRQ_PENDING((u32
)irq_status
);
153 rot_write(val
, ROT_STATUS
);
155 if (irq_status
== ROT_IRQ_STATUS_COMPLETE
) {
156 event_work
->ippdrv
= ippdrv
;
157 event_work
->buf_id
[EXYNOS_DRM_OPS_DST
] =
158 rot
->cur_buf_id
[EXYNOS_DRM_OPS_DST
];
159 queue_work(ippdrv
->event_workq
, &event_work
->work
);
161 DRM_ERROR("the SFR is set illegally\n");
167 static void rotator_align_size(struct rot_context
*rot
, u32 fmt
, u32
*hsize
,
170 struct rot_limit_table
*limit_tbl
= rot
->limit_tbl
;
171 struct rot_limit
*limit
;
175 if (fmt
== ROT_CONTROL_FMT_RGB888
)
176 limit
= &limit_tbl
->rgb888
;
178 limit
= &limit_tbl
->ycbcr420_2p
;
180 /* Get mask for rounding to nearest aligned val */
181 mask
= ~((1 << limit
->align
) - 1);
183 /* Set aligned width */
184 val
= ROT_ALIGN(*hsize
, limit
->align
, mask
);
185 if (val
< limit
->min_w
)
186 *hsize
= ROT_MIN(limit
->min_w
, mask
);
187 else if (val
> limit
->max_w
)
188 *hsize
= ROT_MAX(limit
->max_w
, mask
);
192 /* Set aligned height */
193 val
= ROT_ALIGN(*vsize
, limit
->align
, mask
);
194 if (val
< limit
->min_h
)
195 *vsize
= ROT_MIN(limit
->min_h
, mask
);
196 else if (val
> limit
->max_h
)
197 *vsize
= ROT_MAX(limit
->max_h
, mask
);
202 static int rotator_src_set_fmt(struct device
*dev
, u32 fmt
)
204 struct rot_context
*rot
= dev_get_drvdata(dev
);
207 val
= rot_read(ROT_CONTROL
);
208 val
&= ~ROT_CONTROL_FMT_MASK
;
211 case DRM_FORMAT_NV12
:
212 val
|= ROT_CONTROL_FMT_YCBCR420_2P
;
214 case DRM_FORMAT_XRGB8888
:
215 val
|= ROT_CONTROL_FMT_RGB888
;
218 DRM_ERROR("invalid image format\n");
222 rot_write(val
, ROT_CONTROL
);
227 static inline bool rotator_check_reg_fmt(u32 fmt
)
229 if ((fmt
== ROT_CONTROL_FMT_YCBCR420_2P
) ||
230 (fmt
== ROT_CONTROL_FMT_RGB888
))
236 static int rotator_src_set_size(struct device
*dev
, int swap
,
237 struct drm_exynos_pos
*pos
,
238 struct drm_exynos_sz
*sz
)
240 struct rot_context
*rot
= dev_get_drvdata(dev
);
241 u32 fmt
, hsize
, vsize
;
245 fmt
= rotator_reg_get_fmt(rot
);
246 if (!rotator_check_reg_fmt(fmt
)) {
247 DRM_ERROR("invalid format.\n");
251 /* Align buffer size */
254 rotator_align_size(rot
, fmt
, &hsize
, &vsize
);
256 /* Set buffer size configuration */
257 val
= ROT_SET_BUF_SIZE_H(vsize
) | ROT_SET_BUF_SIZE_W(hsize
);
258 rot_write(val
, ROT_SRC_BUF_SIZE
);
260 /* Set crop image position configuration */
261 val
= ROT_CROP_POS_Y(pos
->y
) | ROT_CROP_POS_X(pos
->x
);
262 rot_write(val
, ROT_SRC_CROP_POS
);
263 val
= ROT_SRC_CROP_SIZE_H(pos
->h
) | ROT_SRC_CROP_SIZE_W(pos
->w
);
264 rot_write(val
, ROT_SRC_CROP_SIZE
);
269 static int rotator_src_set_addr(struct device
*dev
,
270 struct drm_exynos_ipp_buf_info
*buf_info
,
271 u32 buf_id
, enum drm_exynos_ipp_buf_type buf_type
)
273 struct rot_context
*rot
= dev_get_drvdata(dev
);
274 dma_addr_t addr
[EXYNOS_DRM_PLANAR_MAX
];
275 u32 val
, fmt
, hsize
, vsize
;
278 /* Set current buf_id */
279 rot
->cur_buf_id
[EXYNOS_DRM_OPS_SRC
] = buf_id
;
282 case IPP_BUF_ENQUEUE
:
283 /* Set address configuration */
284 for_each_ipp_planar(i
)
285 addr
[i
] = buf_info
->base
[i
];
288 fmt
= rotator_reg_get_fmt(rot
);
289 if (!rotator_check_reg_fmt(fmt
)) {
290 DRM_ERROR("invalid format.\n");
294 /* Re-set cb planar for NV12 format */
295 if ((fmt
== ROT_CONTROL_FMT_YCBCR420_2P
) &&
296 !addr
[EXYNOS_DRM_PLANAR_CB
]) {
298 val
= rot_read(ROT_SRC_BUF_SIZE
);
299 hsize
= ROT_GET_BUF_SIZE_W(val
);
300 vsize
= ROT_GET_BUF_SIZE_H(val
);
303 addr
[EXYNOS_DRM_PLANAR_CB
] =
304 addr
[EXYNOS_DRM_PLANAR_Y
] + hsize
* vsize
;
307 for_each_ipp_planar(i
)
308 rot_write(addr
[i
], ROT_SRC_BUF_ADDR(i
));
310 case IPP_BUF_DEQUEUE
:
311 for_each_ipp_planar(i
)
312 rot_write(0x0, ROT_SRC_BUF_ADDR(i
));
322 static int rotator_dst_set_transf(struct device
*dev
,
323 enum drm_exynos_degree degree
,
324 enum drm_exynos_flip flip
, bool *swap
)
326 struct rot_context
*rot
= dev_get_drvdata(dev
);
329 /* Set transform configuration */
330 val
= rot_read(ROT_CONTROL
);
331 val
&= ~ROT_CONTROL_FLIP_MASK
;
334 case EXYNOS_DRM_FLIP_VERTICAL
:
335 val
|= ROT_CONTROL_FLIP_VERTICAL
;
337 case EXYNOS_DRM_FLIP_HORIZONTAL
:
338 val
|= ROT_CONTROL_FLIP_HORIZONTAL
;
345 val
&= ~ROT_CONTROL_ROT_MASK
;
348 case EXYNOS_DRM_DEGREE_90
:
349 val
|= ROT_CONTROL_ROT_90
;
351 case EXYNOS_DRM_DEGREE_180
:
352 val
|= ROT_CONTROL_ROT_180
;
354 case EXYNOS_DRM_DEGREE_270
:
355 val
|= ROT_CONTROL_ROT_270
;
358 /* Rotation 0 Degree */
362 rot_write(val
, ROT_CONTROL
);
364 /* Check degree for setting buffer size swap */
365 if ((degree
== EXYNOS_DRM_DEGREE_90
) ||
366 (degree
== EXYNOS_DRM_DEGREE_270
))
374 static int rotator_dst_set_size(struct device
*dev
, int swap
,
375 struct drm_exynos_pos
*pos
,
376 struct drm_exynos_sz
*sz
)
378 struct rot_context
*rot
= dev_get_drvdata(dev
);
379 u32 val
, fmt
, hsize
, vsize
;
382 fmt
= rotator_reg_get_fmt(rot
);
383 if (!rotator_check_reg_fmt(fmt
)) {
384 DRM_ERROR("invalid format.\n");
388 /* Align buffer size */
391 rotator_align_size(rot
, fmt
, &hsize
, &vsize
);
393 /* Set buffer size configuration */
394 val
= ROT_SET_BUF_SIZE_H(vsize
) | ROT_SET_BUF_SIZE_W(hsize
);
395 rot_write(val
, ROT_DST_BUF_SIZE
);
397 /* Set crop image position configuration */
398 val
= ROT_CROP_POS_Y(pos
->y
) | ROT_CROP_POS_X(pos
->x
);
399 rot_write(val
, ROT_DST_CROP_POS
);
404 static int rotator_dst_set_addr(struct device
*dev
,
405 struct drm_exynos_ipp_buf_info
*buf_info
,
406 u32 buf_id
, enum drm_exynos_ipp_buf_type buf_type
)
408 struct rot_context
*rot
= dev_get_drvdata(dev
);
409 dma_addr_t addr
[EXYNOS_DRM_PLANAR_MAX
];
410 u32 val
, fmt
, hsize
, vsize
;
413 /* Set current buf_id */
414 rot
->cur_buf_id
[EXYNOS_DRM_OPS_DST
] = buf_id
;
417 case IPP_BUF_ENQUEUE
:
418 /* Set address configuration */
419 for_each_ipp_planar(i
)
420 addr
[i
] = buf_info
->base
[i
];
423 fmt
= rotator_reg_get_fmt(rot
);
424 if (!rotator_check_reg_fmt(fmt
)) {
425 DRM_ERROR("invalid format.\n");
429 /* Re-set cb planar for NV12 format */
430 if ((fmt
== ROT_CONTROL_FMT_YCBCR420_2P
) &&
431 !addr
[EXYNOS_DRM_PLANAR_CB
]) {
433 val
= rot_read(ROT_DST_BUF_SIZE
);
435 hsize
= ROT_GET_BUF_SIZE_W(val
);
436 vsize
= ROT_GET_BUF_SIZE_H(val
);
439 addr
[EXYNOS_DRM_PLANAR_CB
] =
440 addr
[EXYNOS_DRM_PLANAR_Y
] + hsize
* vsize
;
443 for_each_ipp_planar(i
)
444 rot_write(addr
[i
], ROT_DST_BUF_ADDR(i
));
446 case IPP_BUF_DEQUEUE
:
447 for_each_ipp_planar(i
)
448 rot_write(0x0, ROT_DST_BUF_ADDR(i
));
458 static struct exynos_drm_ipp_ops rot_src_ops
= {
459 .set_fmt
= rotator_src_set_fmt
,
460 .set_size
= rotator_src_set_size
,
461 .set_addr
= rotator_src_set_addr
,
464 static struct exynos_drm_ipp_ops rot_dst_ops
= {
465 .set_transf
= rotator_dst_set_transf
,
466 .set_size
= rotator_dst_set_size
,
467 .set_addr
= rotator_dst_set_addr
,
470 static int rotator_init_prop_list(struct exynos_drm_ippdrv
*ippdrv
)
472 struct drm_exynos_ipp_prop_list
*prop_list
= &ippdrv
->prop_list
;
474 prop_list
->version
= 1;
475 prop_list
->flip
= (1 << EXYNOS_DRM_FLIP_VERTICAL
) |
476 (1 << EXYNOS_DRM_FLIP_HORIZONTAL
);
477 prop_list
->degree
= (1 << EXYNOS_DRM_DEGREE_0
) |
478 (1 << EXYNOS_DRM_DEGREE_90
) |
479 (1 << EXYNOS_DRM_DEGREE_180
) |
480 (1 << EXYNOS_DRM_DEGREE_270
);
483 prop_list
->scale
= 0;
488 static inline bool rotator_check_drm_fmt(u32 fmt
)
491 case DRM_FORMAT_XRGB8888
:
492 case DRM_FORMAT_NV12
:
495 DRM_DEBUG_KMS("not support format\n");
500 static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip
)
503 case EXYNOS_DRM_FLIP_NONE
:
504 case EXYNOS_DRM_FLIP_VERTICAL
:
505 case EXYNOS_DRM_FLIP_HORIZONTAL
:
506 case EXYNOS_DRM_FLIP_BOTH
:
509 DRM_DEBUG_KMS("invalid flip\n");
514 static int rotator_ippdrv_check_property(struct device
*dev
,
515 struct drm_exynos_ipp_property
*property
)
517 struct drm_exynos_ipp_config
*src_config
=
518 &property
->config
[EXYNOS_DRM_OPS_SRC
];
519 struct drm_exynos_ipp_config
*dst_config
=
520 &property
->config
[EXYNOS_DRM_OPS_DST
];
521 struct drm_exynos_pos
*src_pos
= &src_config
->pos
;
522 struct drm_exynos_pos
*dst_pos
= &dst_config
->pos
;
523 struct drm_exynos_sz
*src_sz
= &src_config
->sz
;
524 struct drm_exynos_sz
*dst_sz
= &dst_config
->sz
;
527 /* Check format configuration */
528 if (src_config
->fmt
!= dst_config
->fmt
) {
529 DRM_DEBUG_KMS("not support csc feature\n");
533 if (!rotator_check_drm_fmt(dst_config
->fmt
)) {
534 DRM_DEBUG_KMS("invalid format\n");
538 /* Check transform configuration */
539 if (src_config
->degree
!= EXYNOS_DRM_DEGREE_0
) {
540 DRM_DEBUG_KMS("not support source-side rotation\n");
544 switch (dst_config
->degree
) {
545 case EXYNOS_DRM_DEGREE_90
:
546 case EXYNOS_DRM_DEGREE_270
:
548 case EXYNOS_DRM_DEGREE_0
:
549 case EXYNOS_DRM_DEGREE_180
:
553 DRM_DEBUG_KMS("invalid degree\n");
557 if (src_config
->flip
!= EXYNOS_DRM_FLIP_NONE
) {
558 DRM_DEBUG_KMS("not support source-side flip\n");
562 if (!rotator_check_drm_flip(dst_config
->flip
)) {
563 DRM_DEBUG_KMS("invalid flip\n");
567 /* Check size configuration */
568 if ((src_pos
->x
+ src_pos
->w
> src_sz
->hsize
) ||
569 (src_pos
->y
+ src_pos
->h
> src_sz
->vsize
)) {
570 DRM_DEBUG_KMS("out of source buffer bound\n");
575 if ((dst_pos
->x
+ dst_pos
->h
> dst_sz
->vsize
) ||
576 (dst_pos
->y
+ dst_pos
->w
> dst_sz
->hsize
)) {
577 DRM_DEBUG_KMS("out of destination buffer bound\n");
581 if ((src_pos
->w
!= dst_pos
->h
) || (src_pos
->h
!= dst_pos
->w
)) {
582 DRM_DEBUG_KMS("not support scale feature\n");
586 if ((dst_pos
->x
+ dst_pos
->w
> dst_sz
->hsize
) ||
587 (dst_pos
->y
+ dst_pos
->h
> dst_sz
->vsize
)) {
588 DRM_DEBUG_KMS("out of destination buffer bound\n");
592 if ((src_pos
->w
!= dst_pos
->w
) || (src_pos
->h
!= dst_pos
->h
)) {
593 DRM_DEBUG_KMS("not support scale feature\n");
601 static int rotator_ippdrv_start(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
603 struct rot_context
*rot
= dev_get_drvdata(dev
);
606 if (rot
->suspended
) {
607 DRM_ERROR("suspended state\n");
611 if (cmd
!= IPP_CMD_M2M
) {
612 DRM_ERROR("not support cmd: %d\n", cmd
);
616 /* Set interrupt enable */
617 rotator_reg_set_irq(rot
, true);
619 val
= rot_read(ROT_CONTROL
);
620 val
|= ROT_CONTROL_START
;
622 rot_write(val
, ROT_CONTROL
);
627 static struct rot_limit_table rot_limit_tbl_4210
= {
644 static struct rot_limit_table rot_limit_tbl_4x12
= {
661 static struct rot_limit_table rot_limit_tbl_5250
= {
678 static const struct of_device_id exynos_rotator_match
[] = {
680 .compatible
= "samsung,exynos4210-rotator",
681 .data
= &rot_limit_tbl_4210
,
684 .compatible
= "samsung,exynos4212-rotator",
685 .data
= &rot_limit_tbl_4x12
,
688 .compatible
= "samsung,exynos5250-rotator",
689 .data
= &rot_limit_tbl_5250
,
693 MODULE_DEVICE_TABLE(of
, exynos_rotator_match
);
695 static int rotator_probe(struct platform_device
*pdev
)
697 struct device
*dev
= &pdev
->dev
;
698 struct rot_context
*rot
;
699 struct exynos_drm_ippdrv
*ippdrv
;
700 const struct of_device_id
*match
;
704 dev_err(dev
, "cannot find of_node.\n");
708 rot
= devm_kzalloc(dev
, sizeof(*rot
), GFP_KERNEL
);
712 match
= of_match_node(exynos_rotator_match
, dev
->of_node
);
714 dev_err(dev
, "failed to match node\n");
717 rot
->limit_tbl
= (struct rot_limit_table
*)match
->data
;
719 rot
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
720 rot
->regs
= devm_ioremap_resource(dev
, rot
->regs_res
);
721 if (IS_ERR(rot
->regs
))
722 return PTR_ERR(rot
->regs
);
724 rot
->irq
= platform_get_irq(pdev
, 0);
726 dev_err(dev
, "failed to get irq\n");
730 ret
= devm_request_threaded_irq(dev
, rot
->irq
, NULL
,
731 rotator_irq_handler
, IRQF_ONESHOT
, "drm_rotator", rot
);
733 dev_err(dev
, "failed to request irq\n");
737 rot
->clock
= devm_clk_get(dev
, "rotator");
738 if (IS_ERR(rot
->clock
)) {
739 dev_err(dev
, "failed to get clock\n");
740 return PTR_ERR(rot
->clock
);
743 pm_runtime_enable(dev
);
745 ippdrv
= &rot
->ippdrv
;
747 ippdrv
->ops
[EXYNOS_DRM_OPS_SRC
] = &rot_src_ops
;
748 ippdrv
->ops
[EXYNOS_DRM_OPS_DST
] = &rot_dst_ops
;
749 ippdrv
->check_property
= rotator_ippdrv_check_property
;
750 ippdrv
->start
= rotator_ippdrv_start
;
751 ret
= rotator_init_prop_list(ippdrv
);
753 dev_err(dev
, "failed to init property list.\n");
754 goto err_ippdrv_register
;
757 DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv
);
759 platform_set_drvdata(pdev
, rot
);
761 ret
= exynos_drm_ippdrv_register(ippdrv
);
763 dev_err(dev
, "failed to register drm rotator device\n");
764 goto err_ippdrv_register
;
767 dev_info(dev
, "The exynos rotator is probed successfully\n");
772 pm_runtime_disable(dev
);
776 static int rotator_remove(struct platform_device
*pdev
)
778 struct device
*dev
= &pdev
->dev
;
779 struct rot_context
*rot
= dev_get_drvdata(dev
);
780 struct exynos_drm_ippdrv
*ippdrv
= &rot
->ippdrv
;
782 exynos_drm_ippdrv_unregister(ippdrv
);
784 pm_runtime_disable(dev
);
789 static int rotator_clk_crtl(struct rot_context
*rot
, bool enable
)
792 clk_enable(rot
->clock
);
793 rot
->suspended
= false;
795 clk_disable(rot
->clock
);
796 rot
->suspended
= true;
803 #ifdef CONFIG_PM_SLEEP
804 static int rotator_suspend(struct device
*dev
)
806 struct rot_context
*rot
= dev_get_drvdata(dev
);
808 if (pm_runtime_suspended(dev
))
811 return rotator_clk_crtl(rot
, false);
814 static int rotator_resume(struct device
*dev
)
816 struct rot_context
*rot
= dev_get_drvdata(dev
);
818 if (!pm_runtime_suspended(dev
))
819 return rotator_clk_crtl(rot
, true);
826 static int rotator_runtime_suspend(struct device
*dev
)
828 struct rot_context
*rot
= dev_get_drvdata(dev
);
830 return rotator_clk_crtl(rot
, false);
833 static int rotator_runtime_resume(struct device
*dev
)
835 struct rot_context
*rot
= dev_get_drvdata(dev
);
837 return rotator_clk_crtl(rot
, true);
841 static const struct dev_pm_ops rotator_pm_ops
= {
842 SET_SYSTEM_SLEEP_PM_OPS(rotator_suspend
, rotator_resume
)
843 SET_RUNTIME_PM_OPS(rotator_runtime_suspend
, rotator_runtime_resume
,
847 struct platform_driver rotator_driver
= {
848 .probe
= rotator_probe
,
849 .remove
= rotator_remove
,
851 .name
= "exynos-rot",
852 .owner
= THIS_MODULE
,
853 .pm
= &rotator_pm_ops
,
854 .of_match_table
= exynos_rotator_match
,