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

media: mediatek: vcodec: Add vdec enable/disable hardware helpers

Lock, power and clock are highly coupled operations. Adds vdec
enable/disable hardware helpers and uses them.

Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
Reviewed-by: Tzung-Bi Shih<tzungbi@google.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Yunfei Dong and committed by
Mauro Carvalho Chehab
7c6785d2 08a83828

+120 -87
-5
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
··· 193 193 mtk_vcodec_dec_set_default_params(ctx); 194 194 195 195 if (v4l2_fh_is_singular(&ctx->fh)) { 196 - ret = mtk_vcodec_dec_pw_on(dev, MTK_VDEC_LAT0); 197 - if (ret < 0) 198 - goto err_load_fw; 199 196 /* 200 197 * Does nothing if firmware was already loaded. 201 198 */ ··· 249 252 v4l2_m2m_ctx_release(ctx->m2m_ctx); 250 253 mtk_vcodec_dec_release(ctx); 251 254 252 - if (v4l2_fh_is_singular(&ctx->fh)) 253 - mtk_vcodec_dec_pw_off(dev, MTK_VDEC_LAT0); 254 255 v4l2_fh_del(&ctx->fh); 255 256 v4l2_fh_exit(&ctx->fh); 256 257 v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+110 -64
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_pm.c
··· 57 57 } 58 58 EXPORT_SYMBOL_GPL(mtk_vcodec_init_dec_clk); 59 59 60 - int mtk_vcodec_dec_pw_on(struct mtk_vcodec_dev *vdec_dev, int hw_idx) 60 + static int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) 61 61 { 62 - struct mtk_vdec_hw_dev *subdev_dev; 63 - struct mtk_vcodec_pm *pm; 64 62 int ret; 65 - 66 - if (vdec_dev->vdec_pdata->is_subdev_supported) { 67 - subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 68 - if (!subdev_dev) { 69 - mtk_v4l2_err("Failed to get hw dev\n"); 70 - return -EINVAL; 71 - } 72 - pm = &subdev_dev->pm; 73 - } else { 74 - pm = &vdec_dev->pm; 75 - } 76 63 77 64 ret = pm_runtime_resume_and_get(pm->dev); 78 65 if (ret) ··· 67 80 68 81 return ret; 69 82 } 70 - EXPORT_SYMBOL_GPL(mtk_vcodec_dec_pw_on); 71 83 72 - void mtk_vcodec_dec_pw_off(struct mtk_vcodec_dev *vdec_dev, int hw_idx) 84 + static void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm) 73 85 { 74 - struct mtk_vdec_hw_dev *subdev_dev; 75 - struct mtk_vcodec_pm *pm; 76 86 int ret; 77 - 78 - if (vdec_dev->vdec_pdata->is_subdev_supported) { 79 - subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 80 - if (!subdev_dev) { 81 - mtk_v4l2_err("Failed to get hw dev\n"); 82 - return; 83 - } 84 - pm = &subdev_dev->pm; 85 - } else { 86 - pm = &vdec_dev->pm; 87 - } 88 87 89 88 ret = pm_runtime_put_sync(pm->dev); 90 89 if (ret) 91 90 mtk_v4l2_err("pm_runtime_put_sync fail %d", ret); 92 91 } 93 - EXPORT_SYMBOL_GPL(mtk_vcodec_dec_pw_off); 94 92 95 - void mtk_vcodec_dec_clock_on(struct mtk_vcodec_dev *vdec_dev, int hw_idx) 93 + static void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm) 96 94 { 97 - struct mtk_vdec_hw_dev *subdev_dev; 98 - struct mtk_vcodec_pm *pm; 99 95 struct mtk_vcodec_clk *dec_clk; 100 96 int ret, i; 101 - 102 - if (vdec_dev->vdec_pdata->is_subdev_supported) { 103 - subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 104 - if (!subdev_dev) { 105 - mtk_v4l2_err("Failed to get hw dev\n"); 106 - return; 107 - } 108 - pm = &subdev_dev->pm; 109 - enable_irq(subdev_dev->dec_irq); 110 - } else { 111 - pm = &vdec_dev->pm; 112 - enable_irq(vdec_dev->dec_irq); 113 - } 114 97 115 98 dec_clk = &pm->vdec_clk; 116 99 for (i = 0; i < dec_clk->clk_num; i++) { ··· 97 140 for (i -= 1; i >= 0; i--) 98 141 clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk); 99 142 } 100 - EXPORT_SYMBOL_GPL(mtk_vcodec_dec_clock_on); 101 143 102 - void mtk_vcodec_dec_clock_off(struct mtk_vcodec_dev *vdec_dev, int hw_idx) 144 + static void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm) 103 145 { 104 - struct mtk_vdec_hw_dev *subdev_dev; 105 - struct mtk_vcodec_pm *pm; 106 146 struct mtk_vcodec_clk *dec_clk; 107 147 int i; 108 - 109 - if (vdec_dev->vdec_pdata->is_subdev_supported) { 110 - subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 111 - if (!subdev_dev) { 112 - mtk_v4l2_err("Failed to get hw dev\n"); 113 - return; 114 - } 115 - pm = &subdev_dev->pm; 116 - disable_irq(subdev_dev->dec_irq); 117 - } else { 118 - pm = &vdec_dev->pm; 119 - disable_irq(vdec_dev->dec_irq); 120 - } 121 148 122 149 dec_clk = &pm->vdec_clk; 123 150 for (i = dec_clk->clk_num - 1; i >= 0; i--) 124 151 clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk); 125 152 } 126 - EXPORT_SYMBOL_GPL(mtk_vcodec_dec_clock_off); 153 + 154 + static void mtk_vcodec_dec_enable_irq(struct mtk_vcodec_dev *vdec_dev, int hw_idx) 155 + { 156 + struct mtk_vdec_hw_dev *subdev_dev; 157 + 158 + if (!test_bit(hw_idx, vdec_dev->subdev_bitmap)) 159 + return; 160 + 161 + if (vdec_dev->vdec_pdata->is_subdev_supported) { 162 + subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 163 + if (subdev_dev) 164 + enable_irq(subdev_dev->dec_irq); 165 + else 166 + mtk_v4l2_err("Failed to get hw dev\n"); 167 + } else { 168 + enable_irq(vdec_dev->dec_irq); 169 + } 170 + } 171 + 172 + static void mtk_vcodec_dec_disable_irq(struct mtk_vcodec_dev *vdec_dev, int hw_idx) 173 + { 174 + struct mtk_vdec_hw_dev *subdev_dev; 175 + 176 + if (!test_bit(hw_idx, vdec_dev->subdev_bitmap)) 177 + return; 178 + 179 + if (vdec_dev->vdec_pdata->is_subdev_supported) { 180 + subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 181 + if (subdev_dev) 182 + disable_irq(subdev_dev->dec_irq); 183 + else 184 + mtk_v4l2_err("Failed to get hw dev\n"); 185 + } else { 186 + disable_irq(vdec_dev->dec_irq); 187 + } 188 + } 189 + 190 + static struct mtk_vcodec_pm *mtk_vcodec_dec_get_pm(struct mtk_vcodec_dev *vdec_dev, 191 + int hw_idx) 192 + { 193 + struct mtk_vdec_hw_dev *subdev_dev; 194 + 195 + if (!test_bit(hw_idx, vdec_dev->subdev_bitmap)) 196 + return NULL; 197 + 198 + if (vdec_dev->vdec_pdata->is_subdev_supported) { 199 + subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx); 200 + if (subdev_dev) 201 + return &subdev_dev->pm; 202 + 203 + mtk_v4l2_err("Failed to get hw dev\n"); 204 + return NULL; 205 + } 206 + 207 + return &vdec_dev->pm; 208 + } 209 + 210 + static void mtk_vcodec_dec_child_dev_on(struct mtk_vcodec_dev *vdec_dev, 211 + int hw_idx) 212 + { 213 + struct mtk_vcodec_pm *pm; 214 + 215 + pm = mtk_vcodec_dec_get_pm(vdec_dev, hw_idx); 216 + if (pm) { 217 + mtk_vcodec_dec_pw_on(pm); 218 + mtk_vcodec_dec_clock_on(pm); 219 + } 220 + } 221 + 222 + static void mtk_vcodec_dec_child_dev_off(struct mtk_vcodec_dev *vdec_dev, 223 + int hw_idx) 224 + { 225 + struct mtk_vcodec_pm *pm; 226 + 227 + pm = mtk_vcodec_dec_get_pm(vdec_dev, hw_idx); 228 + if (pm) { 229 + mtk_vcodec_dec_clock_off(pm); 230 + mtk_vcodec_dec_pw_off(pm); 231 + } 232 + } 233 + 234 + void mtk_vcodec_dec_enable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx) 235 + { 236 + mutex_lock(&ctx->dev->dec_mutex[hw_idx]); 237 + 238 + if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) && 239 + hw_idx == MTK_VDEC_CORE) 240 + mtk_vcodec_dec_child_dev_on(ctx->dev, MTK_VDEC_LAT0); 241 + mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx); 242 + 243 + mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx); 244 + } 245 + EXPORT_SYMBOL_GPL(mtk_vcodec_dec_enable_hardware); 246 + 247 + void mtk_vcodec_dec_disable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx) 248 + { 249 + mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx); 250 + 251 + mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx); 252 + if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) && 253 + hw_idx == MTK_VDEC_CORE) 254 + mtk_vcodec_dec_child_dev_off(ctx->dev, MTK_VDEC_LAT0); 255 + 256 + mutex_unlock(&ctx->dev->dec_mutex[hw_idx]); 257 + } 258 + EXPORT_SYMBOL_GPL(mtk_vcodec_dec_disable_hardware);
+2 -4
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_pm.h
··· 11 11 12 12 int mtk_vcodec_init_dec_clk(struct platform_device *pdev, struct mtk_vcodec_pm *pm); 13 13 14 - int mtk_vcodec_dec_pw_on(struct mtk_vcodec_dev *vdec_dev, int hw_idx); 15 - void mtk_vcodec_dec_pw_off(struct mtk_vcodec_dev *vdec_dev, int hw_idx); 16 - void mtk_vcodec_dec_clock_on(struct mtk_vcodec_dev *vdec_dev, int hw_idx); 17 - void mtk_vcodec_dec_clock_off(struct mtk_vcodec_dev *vdec_dev, int hw_idx); 14 + void mtk_vcodec_dec_enable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx); 15 + void mtk_vcodec_dec_disable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx); 18 16 19 17 #endif /* _MTK_VCODEC_DEC_PM_H_ */
+6 -14
drivers/media/platform/mediatek/vcodec/vdec_drv_if.c
··· 38 38 return -EINVAL; 39 39 } 40 40 41 - mtk_vdec_lock(ctx); 42 - mtk_vcodec_dec_clock_on(ctx->dev, ctx->hw_id); 41 + mtk_vcodec_dec_enable_hardware(ctx, ctx->hw_id); 43 42 ret = ctx->dec_if->init(ctx); 44 - mtk_vcodec_dec_clock_off(ctx->dev, ctx->hw_id); 45 - mtk_vdec_unlock(ctx); 43 + mtk_vcodec_dec_disable_hardware(ctx, ctx->hw_id); 46 44 47 45 return ret; 48 46 } ··· 68 70 if (!ctx->drv_handle) 69 71 return -EIO; 70 72 71 - mtk_vdec_lock(ctx); 72 - 73 + mtk_vcodec_dec_enable_hardware(ctx, ctx->hw_id); 73 74 mtk_vcodec_set_curr_ctx(ctx->dev, ctx, ctx->hw_id); 74 - mtk_vcodec_dec_clock_on(ctx->dev, ctx->hw_id); 75 75 ret = ctx->dec_if->decode(ctx->drv_handle, bs, fb, res_chg); 76 - mtk_vcodec_dec_clock_off(ctx->dev, ctx->hw_id); 77 76 mtk_vcodec_set_curr_ctx(ctx->dev, NULL, ctx->hw_id); 78 - 79 - mtk_vdec_unlock(ctx); 77 + mtk_vcodec_dec_disable_hardware(ctx, ctx->hw_id); 80 78 81 79 return ret; 82 80 } ··· 97 103 if (!ctx->drv_handle) 98 104 return; 99 105 100 - mtk_vdec_lock(ctx); 101 - mtk_vcodec_dec_clock_on(ctx->dev, ctx->hw_id); 106 + mtk_vcodec_dec_enable_hardware(ctx, ctx->hw_id); 102 107 ctx->dec_if->deinit(ctx->drv_handle); 103 - mtk_vcodec_dec_clock_off(ctx->dev, ctx->hw_id); 104 - mtk_vdec_unlock(ctx); 108 + mtk_vcodec_dec_disable_hardware(ctx, ctx->hw_id); 105 109 106 110 ctx->drv_handle = NULL; 107 111 }
+2
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
··· 212 212 return; 213 213 214 214 ctx = lat_buf->ctx; 215 + mtk_vcodec_dec_enable_hardware(ctx, MTK_VDEC_CORE); 215 216 mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE); 216 217 217 218 lat_buf->core_decode(lat_buf); 218 219 219 220 mtk_vcodec_set_curr_ctx(dev, NULL, MTK_VDEC_CORE); 221 + mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE); 220 222 vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); 221 223 222 224 if (!list_empty(&ctx->msg_queue.lat_ctx.ready_queue)) {